<!DOCTYPE html><!-- ###BEGIN###{EventSubscriptions} --><!-- ###END###{EventSubscriptions} --><!-- ###BEGIN###{Desktop-Settings} --><!-- ###END###{Desktop-Settings} --><!-- ###BEGIN###{Desktop-Multi} --><!-- ###END###{Desktop-Multi} --><!-- ###BEGIN###{ComputerSelectorNoImages} --><!-- ###END###{ComputerSelectorNoImages} --><!-- ###BEGIN###{ComputerSelector-Local-ScriptOnly} --><!-- ###END###{ComputerSelector-Local-ScriptOnly} --><html lang="fr" style="height:100%"><head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"> 
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta name="format-detection" content="telephone=no">
    <link rel="icon" type="image/png" href=""> <!-- Stop favicon.ico from loading -->
<!-- ###BEGIN###{Look-Commander} -->
    <!-- ###BEGIN###{ComputerSelector} -->
    <link type="text/css" href="styles-commander-node.css" media="screen" rel="stylesheet" title="CSS">
    <!-- ###END###{ComputerSelector} -->
    <!-- ###BEGIN###{!ComputerSelector} -->
    <link type="text/css" href="styles-commander.css" media="screen" rel="stylesheet" title="CSS">
    <!-- ###END###{!ComputerSelector} -->
<!-- ###END###{Look-Commander} -->
<!-- ###BEGIN###{Look-Branded} -->
    <link type="text/css" href="styles-branded.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-Branded} -->
<!-- ###BEGIN###{Look-ISDU} -->
    <link type="text/css" href="styles-isdu.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-ISDU} -->
<!-- ###BEGIN###{Look-BrandedCommander} -->
    <link type="text/css" href="styles-brandedcommander.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-BrandedCommander} -->
<!-- ###BEGIN###{Look-Unite} -->
    <link type="text/css" href="styles-unite.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-Unite} -->
<!-- ###BEGIN###{Look-MeshCentral} -->
    <link type="text/css" href="styles-mesh.css" media="screen" rel="stylesheet" title="CSS">
<!-- ###END###{Look-MeshCentral} -->
    <script type="text/javascript" src="common-0.0.1.js"></script>
<!-- ###BEGIN###{Mode-LMS} -->
    <script type="text/javascript" src="amt-lms-0.0.1.js"></script>
    <script type="text/javascript" src="amt-wsman-ws-0.2.0.js"></script>
<!-- ###END###{Mode-LMS} -->
<!-- ###BEGIN###{Mode-NodeWebkit} -->
    <script type="text/javascript" src="amt-wsman-node-0.2.0.js"></script>
    <script type="text/javascript" src="amt-redir-node-0.1.0.js"></script>
    <script type="text/javascript" src="amt-scanner-0.1.0.js"></script>
<!-- ###END###{Mode-NodeWebkit} -->
<!-- ###BEGIN###{Mode-WebSite} -->
    <script type="text/javascript" src="amt-wsman-ws-0.2.0.js"></script>
    <script type="text/javascript" src="amt-redir-ws-0.1.0.js"></script>
<!-- ###END###{Mode-WebSite} -->
<!-- ###BEGIN###{Mode-Firmware} -->
    <script type="text/javascript" src="amt-wsman-ajax-0.2.0.js"></script>
    <script type="text/javascript" src="amt-redir-ws-0.1.0.js"></script>
<!-- ###END###{Mode-Firmware} -->
<!-- ###BEGIN###{IDER} -->
    <script type="text/javascript" src="amt-ider-ws-0.0.1.js"></script>
    <!-- ###BEGIN###{IDER-IMRSDK} -->
    <script type="text/javascript" src="amt-ider-node-0.0.1.js"></script>
    <!-- ###END###{IDER-IMRSDK} -->
    <!-- ###BEGIN###{Mode-MeshCentral2} -->
    <script type="text/javascript" src="amt-ider-server-ws-0.0.1.js"></script>
    <!-- ###END###{Mode-MeshCentral2} -->
<!-- ###END###{IDER} -->
<!-- ###BEGIN###{Mode-MeshCentral2} -->
    <script type="text/javascript" src="amt-wsman-ws-0.2.0.js"></script>
    <script type="text/javascript" src="amt-redir-ws-0.1.0.js"></script>
<!-- ###END###{Mode-MeshCentral2} -->
    <script type="text/javascript" src="amt-wsman-0.2.0.js"></script>
    <script type="text/javascript" src="amt-0.2.0.js"></script>
<!-- ###BEGIN###{Certificates} -->
    <script type="text/javascript" src="forge.js/forge.bundle.js"></script>
    <script type="text/javascript" src="amt-certificates-0.0.1.js"></script>
<!-- ###END###{Certificates} -->
<!-- ###BEGIN###{Scripting} -->
    <script type="text/javascript" src="amt-script-0.2.0.js"></script>
<!-- ###END###{Scripting} -->
<!-- ###BEGIN###{Desktop} -->
    <script type="text/javascript" src="amt-desktop-0.0.2.js"></script>
    <style type="text/css">
        .rb { cursor: pointer; border: none; float: right; font-size: 130%; margin-right: 4px; }
    </style>
<!-- ###END###{Desktop} -->
<!-- ###BEGIN###{DesktopInband} -->
    <script type="text/javascript" src="agent-desktop-0.0.2.js"></script>
    <script type="text/javascript" src="agent-redir-rtc-0.1.0.js"></script>
<!-- ###END###{DesktopInband} -->
<!-- ###BEGIN###{Terminal} -->
    <script type="text/javascript" src="amt-terminal-0.0.2.js"></script>
<!-- ###END###{Terminal} -->
<!-- ###BEGIN###{PowerControl-Advanced} -->
<!-- ###BEGIN###{PowerControl-OneClick} -->
    <script type="text/javascript" src="webserver-0.0.1.js"></script>
<!-- ###END###{PowerControl-Advanced} -->
<!-- ###END###{PowerControl-OneClick} -->
<!-- ###BEGIN###{Inflate} -->
    <script type="text/javascript" src="zlib.js"></script>
    <script type="text/javascript" src="zlib-inflate.js"></script>
    <script type="text/javascript" src="zlib-adler32.js"></script>
    <script type="text/javascript" src="zlib-crc32.js"></script>
<!-- ###END###{Inflate} -->
<!-- ###BEGIN###{USBSetup} -->
    <script type="text/javascript" src="amt-setupbin-0.1.0.js"></script>
<!-- ###END###{USBSetup} -->
<!-- ###BEGIN###{FileSaver} -->
    <script type="text/javascript" src="filesaver.1.1.20151003.js"></script>
<!-- ###END###{FileSaver} -->
<!-- ###BEGIN###{MeshServerConnect} -->
    <script type="text/javascript" src="meshcentral-server-0.2.0.js"></script>
    <script type="text/javascript" src="websocket-wrapper-0.2.0.js"></script>
<!-- ###END###{MeshServerConnect} -->
<!-- ###BEGIN###{Mode-LMS} -->
    <style type="text/css">
        .menuitem { cursor: pointer; border: none; padding:5px; }
        .menuitem:hover { background-color: #6b9dc7; }
    </style>
<!-- ###END###{Mode-LMS} -->
<!-- ###BEGIN###{ComputerSelector} -->
    <style type="text/css">
        .menuitem { cursor: pointer; border: none; padding:5px; }
        .menuitem:hover { background-color: #6b9dc7; }
    </style>
<!-- ###END###{ComputerSelector} -->
<!-- ###BEGIN###{ContextMenus} -->
    <style>
        .contextMenu {
            background: #F9F9F9;
            box-shadow: 0 0 12px rgba( 0, 0, 0, .3 );
            border: 1px solid #ccc;
            /*border-radius: 4px;*/
            position: absolute;
            top: 0;
            left: 0;
            list-style: none;
            margin: 0;
            padding: 5px;
            min-width: 100px;
            max-width: 150px;
            z-index: 500;
        }

        .cmtext {
            color: #444;
            display: inline-block;
            padding-left: 8px;
            padding-right: 8px;
            padding-top: 5px;
            padding-bottom: 5px;
            text-decoration: none;
            width: 85%;
            cursor: default;
            overflow: hidden;
            position: relative;
        }

            .cmtext:hover {
                color: #f9f9f9;
                background: #999;
            }
    </style>
<!-- ###END###{ContextMenus} -->
<!-- ###BEGIN###{DesktopInbandFiles} -->
    <style>
        .fileIcon1 {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            float: left;
            margin-top: 1px;
        }

        .fileIcon2 {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            float: left;
            margin-top: 1px;
        }

        .fileIcon3 {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            float: left;
            margin-top: 1px;
        }

        .filelist {
            -moz-user-select: none;
            -khtml-user-select: none;
            -webkit-user-select: none;
            -o-user-select: none;
            cursor: default;
            -khtml-user-drag: element;
            background-color: white;
            clear: both;
        }

        .fsize {
            float: right;
            text-align: right;
            width: 180px;
        }
    </style>
<!-- ###END###{DesktopInbandFiles} -->
<!-- ###BEGIN###{SessionRecording} -->
    <style>
        .cameraIcon {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            margin-top:2px;
            margin-right:4px;
            cursor:pointer;
            float:right;
        }

        .videoIcon {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            margin-top:2px;
            margin-right:4px;
            cursor:pointer;
            float:right;
        }

        .videoIconRed {
            background: url();
            height: 16px;
            width: 16px;
            cursor: pointer;
            border: none;
            margin-top:2px;
            margin-right:4px;
            cursor:pointer;
            float:right;
        }
    </style>
<!-- ###END###{SessionRecording} -->
<!-- ###BEGIN###{Look-Commander} -->
    <!-- ###BEGIN###{!ComputerSelector-Local-ScriptOnly} -->
    <!-- ###BEGIN###{!Mode-LMS} -->
    <title>MeshCommander</title>
    <!-- ###END###{!Mode-LMS} -->
    <!-- ###BEGIN###{Mode-LMS} -->
    <title>LMS MeshCommander</title>
    <!-- ###END###{Mode-LMS} -->
    <!-- ###END###{!ComputerSelector-Local-ScriptOnly} -->
    <!-- ###BEGIN###{ComputerSelector-Local-ScriptOnly} -->
    <title>ScriptCommander</title>
    <!-- ###END###{ComputerSelector-Local-ScriptOnly} -->
<!-- ###END###{Look-Commander} -->
<!-- ###BEGIN###{Look-Branded} -->
    <title>Intel® Active Management Technology</title>
<!-- ###END###{Look-Branded} -->
<!-- ###BEGIN###{Look-ISDU} -->
    <title>Intel® System Defense Utility</title>
<!-- ###END###{Look-ISDU} -->
<!-- ###BEGIN###{Look-BrandedCommander} -->
    <title>Intel® Manageability Commander</title>
<!-- ###END###{Look-BrandedCommander} -->
<!-- ###BEGIN###{Look-Unite} -->
    <title>Intel® Unite - Hardware Management</title>
<!-- ###END###{Look-Unite} -->
</head>
<!-- ###BEGIN###{!ContextMenus} -->
<body onunload="cleanup()" oncontextmenu="handleContextMenu(event)">
<!-- ###END###{!ContextMenus} -->
<!-- ###BEGIN###{ContextMenus} -->

<!-- ###END###{ContextMenus} -->
    <div id="id_topheader" class="header">
        <!-- ###BEGIN###{!Look-MeshCentral} -->
        <!-- ###BEGIN###{Look-Unite} -->
        <table style="width:100%;height:55px">
            <tbody><tr>
                <td valign="top" nowrap="nowrap">
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Active Management Technology</p>
                    <p class="top2" id="id_computername"></p>
                </td>
                <td valign="top">
                    <img width="165" height="42" align="right" style="border:0;margin-top:10px;margin-right:12px" src="images-unite/title.png">
                </td>
            </tr>
        </tbody></table>
        <!-- ###END###{Look-Unite} -->
        <!-- ###BEGIN###{Look-ISDU} -->
        <div>
            <div style="background-image:url(images-isdu/LogoWhite42.png);width:63px;height:42px;float:right;margin-top:14px;margin-right:20px;padding:0"></div>
            <div style="width:425px;height:69px"><div style="background-image:url(images-isdu/ISDUTitle.png);position:relative;top:26px;left:20px;width:282px;height:20px"></div></div>
            <p id="id_computername" style="display:none"></p>
        </div>
        <!-- ###END###{Look-ISDU} -->
        <!-- ###BEGIN###{Look-BrandedCommander} -->
        <!-- ###BEGIN###{Mode-NodeWebkit} -->
        <div>
            <div style="background-image:url(images-brandedcommander/LogoWhite42.png);width:63px;height:42px;float:right;margin-top:14px;margin-right:20px;padding:0"></div>
            <div style="width:425px;height:69px"><div style="background-image:url(images-brandedcommander/CommanderTitle.png);position:relative;top:21px;left:20px;width:443px;height:33px"></div></div>
            <p id="id_computername" style="display:none"></p>
        </div>
        <!-- ###END###{Mode-NodeWebkit} -->
        <!-- ###BEGIN###{!Mode-NodeWebkit} -->
        <table style="width:100%;height:55px">
            <tbody><tr>
                <td valign="top" nowrap="nowrap">
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Manageability Commander</p>
                    <p class="top2" id="id_computername"></p>
                </td>
                <td valign="top">
                    <img width="73" height="53" align="right" style="border:0" src="images-branded/logo.gif">
                </td>
            </tr>
        </tbody></table>
        <!-- ###END###{!Mode-NodeWebkit} -->
        <!-- ###END###{Look-BrandedCommander} -->
        <!-- ###BEGIN###{!Look-ISDU} -->
        <!-- ###BEGIN###{!Look-BrandedCommander} -->
        <table class="topCell" style="width:100%;height:55px">
            <tbody><tr>
                <td valign="top" nowrap="nowrap">
                    <!-- ###BEGIN###{Look-Commander} -->
                    <!-- ###BEGIN###{Switchbox} -->
                    <p class="top1">Manageability Switchbox</p>
                    <!-- ###END###{Switchbox} -->
                    <!-- ###BEGIN###{!Switchbox} -->
                    <!-- ###BEGIN###{!ComputerSelector-Local-ScriptOnly} -->

                    <!-- ###BEGIN###{!Mode-LMS} -->
                    <p class="top1">MeshCommander</p>
                    <!-- ###END###{!Mode-LMS} -->
                    <!-- ###BEGIN###{Mode-LMS} -->
                    <p class="top1">LMS MeshCommander</p>
                    <!-- ###END###{Mode-LMS} -->
                    <!-- ###END###{!ComputerSelector-Local-ScriptOnly} -->
                    <!-- ###BEGIN###{ComputerSelector-Local-ScriptOnly} -->
                    <p class="top1">ScriptCommander</p>
                    <!-- ###END###{ComputerSelector-Local-ScriptOnly} -->
                    <!-- ###END###{!Switchbox} -->
                    <!-- ###END###{Look-Commander} -->
                    <!-- ###BEGIN###{Look-Intel-AMT} -->
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Active Management Technology</p>
                    <!-- ###END###{Look-Intel-AMT} -->
                    <!-- ###BEGIN###{Look-Intel-SM} -->
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Standard Manageability</p>
                    <!-- ###END###{Look-Intel-SM} -->
                    <!-- ###BEGIN###{Look-Intel-SBT} -->
                    <p class="top1">Intel<sup style="font-size:10px">®</sup>&nbsp;Small Buisness Technology</p>
                    <!-- ###END###{Look-Intel-SBT} -->
                    <p class="top2" id="id_computername"></p>
                </td>
                <td valign="top">
                    <!-- ###BEGIN###{!Mode-LMS} -->
                    <!-- ###BEGIN###{!Mode-Firmware} -->
                    <!-- ###BEGIN###{Look-Commander} -->
                    <img width="166" height="64" align="right" style="border:0" src="images-commander/logo.png">
                    <!-- ###END###{Look-Commander} -->
                    <!-- ###END###{!Mode-Firmware} -->
                    <!-- ###END###{!Mode-LMS} -->
                    <!-- ###BEGIN###{Look-Branded} -->
                    <img width="73" height="53" align="right" style="border:0" src="images-branded/logo.gif">
                    <!-- ###END###{Look-Branded} -->
                </td>
            </tr>
        </tbody></table>
        <!-- ###END###{!Look-BrandedCommander} -->
        <!-- ###END###{!Look-ISDU} -->
        <!-- ###END###{!Look-MeshCentral} -->
        <!-- ###BEGIN###{Mode-MeshCentral2} -->
        <table id="id_KVMTable" cellpadding="0" cellspacing="0" style="width: 100%; padding: 0px; padding: 0px; margin-top: 0px">
            <tbody><tr>
                <td id="id_normalScreenToolbar" class="style6">
                    <div>
                        &nbsp;<input type="button" class="connectbutton" id="xconnectbutton1" value="Relier" onclick="connectButtonfunction(event, false)" onkeypress="return false" onkeydown="return false">
                        &nbsp;<span id="constatus"></span>
                    </div>
                </td>
            </tr>
        </tbody></table>
        <!-- ###END###{Mode-MeshCentral2} -->
        <div class="progressbar">
            <!-- ###BEGIN###{Look-MeshCentral} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-MeshCentral} -->
            <!-- ###BEGIN###{Look-Commander} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-Commander} -->
            <!-- ###BEGIN###{Look-Branded} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:orange"></div>
            <!-- ###END###{Look-Branded} -->
            <!-- ###BEGIN###{Look-ISDU} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-ISDU} -->
            <!-- ###BEGIN###{Look-BrandedCommander} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-BrandedCommander} -->
            <!-- ###BEGIN###{Look-Unite} -->
            <div id="id_progressbar" style="height:2px;width:0%;background-color:red"></div>
            <!-- ###END###{Look-Unite} -->
        </div>
    </div>
    <div id="id_messageview" class="fullcell" style="text-align:center;padding-top:100px;font-size:20px">
        <!-- ###BEGIN###{Look-MeshCentral} -->
        <span id="id_messageviewstr">Débranché</span>
        <!-- ###END###{Look-MeshCentral} -->
        <!-- ###BEGIN###{!Look-MeshCentral} -->
        <span id="id_messageviewstr">Chargement...</span>
        <!-- ###END###{!Look-MeshCentral} -->
        <!-- ###BEGIN###{ComputerSelector} -->
        <br><br><input id="id_messageviewbutton" type="button" value="proche" onclick="disconnect()">
        <!-- ###END###{ComputerSelector} -->
        <!-- ###BEGIN###{Mode-LMS} -->
        <br><br><input type="button" value="proche" onclick="disconnect()">
        <!-- ###END###{Mode-LMS} -->
    </div>
    <!-- ###BEGIN###{Mode-LMS} -->
    <div id="id_lmsMainPanel" class="fullcell" style="display:none">
        <div style="background-color:lightgray;height:24px;margin-bottom:6px;padding-top:2px">
            <div id="id_lmsToolBarContent" style="display:none">
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <div style="float:left;height:26px;width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </div>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <div>
                    <input type="button" value="Rafraîchir" onclick="lmsRefresh()">
                    <input id="id_lmsActivateButton" type="button" value="Activate..." style="display:none" onclick="lmsActivate()">
                    <input id="id_lmsDeactivateButton" type="button" value="Deactivate..." style="display:none" onclick="lmsDeactivate()">
                    <input id="id_lmsLoginButton" type="button" value="Login..." style="display:none" onclick="lmsLogin()">
                    <input id="id_lmsConfigureButton" type="button" value="Intel® AMT Login..." style="display:none" onclick="lmsConfigure()">
                </div>
            </div>
        </div>
        <div id="id_lmsData" style="margin:10px"></div>
        <div id="id_lmsData2" style="margin:10px"></div>
    </div>
    <!-- ###END###{Mode-LMS} -->
    <!-- ###BEGIN###{PowerControl-OneClick} -->
    <div id="TransferNotification" style="display:none;background-color:lightgrey;position:absolute;left:10px;bottom:10px;border-radius:5px;padding:4px;z-index:1000;box-shadow:0px 0px 10px #333"></div>
    <!-- ###END###{PowerControl-OneClick} -->
    <!-- ###BEGIN###{Mode-NodeWebkit} -->
    <div id="LeftSideToolBar" style="position:absolute;left:0px;bottom:0px;width:52px;top:69px;background:#113962;background:linear-gradient(to bottom, #104893 0%,#113962 100%);color:white;display:none">
        <div style="height:23px"></div>
        <div id="LeftMenuMyDevices" class="lbbutton lbbuttonsel2" title="Gestion d'ordinateur" onclick="go(101)">
            <div class="lb1" style="position:absolute;top:6px;left:6px"></div>
        </div>
        <div id="LeftMenuMyCerts" class="lbbutton" title="Gestionnaire de certificats" onclick="go(103)">
            <div class="lb2" style="position:absolute;top:6px;left:6px"></div>
        </div>
        <div id="LeftMenuMyUsb" class="lbbutton" title="Gestionnaire Setup.bin" onclick="go(102)">
            <div class="lb3" style="position:absolute;top:6px;left:6px"></div>
        </div>
        <!-- ###BEGIN###{SessionRecording} -->
        <div id="LeftMenuPlayer" class="lbbutton" title="Lecteur de session" onclick="go(104)">
            <div class="lb4" style="position:absolute;top:6px;left:6px"></div>
        </div>
        <!-- ###END###{SessionRecording} -->
    </div>
    <!-- ###END###{Mode-NodeWebkit} -->
    <!-- ###BEGIN###{ComputerSelector} -->
    <div id="id_computerSelector" class="fullcell" style="display:none">
        <!-- ###BEGIN###{Mode-NodeWebkit} -->
        <div id="UpdateNotification" style="display:none;background-color:lightgrey;position:absolute;left:10px;bottom:10px;border-radius:5px;padding:10px;z-index:1000;box-shadow: 0px 0px 20px #888888">
            <a style="cursor:pointer;color:blue" onclick="NW_PerformUpdate()"><u id="UpdateNotificationText"></u></a> &nbsp; <span onclick="NW_HideUpdateNotification()" style="cursor:pointer;font-size:15px">✖</span>
        </div>
        <!-- ###END###{Mode-NodeWebkit} -->
        <!-- ###BEGIN###{ComputerSelectorToolbar} -->
        <table style="background-color:#808080;width:100%">
            <tbody><tr>
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <td id="toolmenuicondiv" style="width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </td>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <!-- ###BEGIN###{MeshServerConnect} -->
                <td id="idx_disconnectMeshCentralButton" style="display:none">
                    <input type="button" value="Déconnecter" onclick="meshCentralDisconnect()">
                </td>
                <!-- ###END###{MeshServerConnect} -->
                <td>
                    <span id="id_noScriptButtons">
                        <!-- ###BEGIN###{ComputerSelector-Remote} -->
                        <input type="button" value="Rafraîchir" onclick="loadServerComputerList()">
                        <!-- ###END###{ComputerSelector-Remote} -->
                        <!-- ###BEGIN###{ComputerSelector-Local} -->
                        <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                        <input type="button" value="Nouveau..." onclick="newComputerList()">
                        <input type="button" value="Ouvert..." onclick="openComputerList()">
                        <!-- ###BEGIN###{FileSaver} -->
                        <input id="saveComputersButton" type="button" value="Sauver..." onclick="saveComputerList()">
                        <!-- ###END###{FileSaver} -->
                        <!-- ###END###{!Mode-NodeWebkit} -->
                        <input type="button" value="Ajouter un ordinateur ..." onclick="addComputer()">
                        <!-- ###END###{ComputerSelector-Local} -->
                        <!-- ###BEGIN###{ComputerSelectorScanner} -->
                        <!-- ###BEGIN###{Mode-NodeWebkit} -->
                        <input type="button" value="Analyse..." onclick="showScanDialog()">
                        <!-- ###END###{Mode-NodeWebkit} -->
                        <!-- ###END###{ComputerSelectorScanner} -->
                    </span>
                    <!-- ###BEGIN###{Scripting} -->
                    <!-- ###BEGIN###{!Look-BrandedCommander} -->
                    <input id="idx_runScriptOnComputersButton" type="button" value="Script de lancement..." onclick="mscript_runScriptDlg()">
                    <!-- ###END###{!Look-BrandedCommander} -->
                    <!-- ###BEGIN###{Look-BrandedCommander} -->
                    <input id="idx_runScriptOnComputersButton" type="button" value="Script de lancement..." onclick="mscript_runScriptDlg()" style="display:none">
                    <!-- ###END###{Look-BrandedCommander} -->
                    <!-- ###END###{Scripting} -->
                </td>
                <td style="text-align:right">
                    <!-- ###BEGIN###{!Look-BrandedCommander} -->
                    <input id="computerFilter" placeholder="Filtre" onkeyup="computerFilterFunc()" autocomplete="off" onfocus="onFilterFocus(true)" onblur="onFilterFocus(false)">
                    <!-- ###END###{!Look-BrandedCommander} -->
                </td>
            </tr>
        </tbody></table>
        <!-- ###BEGIN###{ComputerSelector-Local} -->
        <div id="id_computerListParent" style="position:fixed;top:96px;left:0;right:300px;bottom:0;overflow-y:scroll" cm="Add&nbsp;Computer...#addComputer()">
        <!-- ###END###{ComputerSelector-Local} -->
        <!-- ###BEGIN###{!ComputerSelector-Local} -->
            <div id="id_computerListParent" style="position:fixed;top:96px;left:0;right:300px;bottom:0;overflow-y:scroll">
        <!-- ###END###{!ComputerSelector-Local} -->
                <div id="id_noKnownComputers" style="text-align:center;margin-top:36px;color:gray">
                    <span style="font-size:20px">Aucun ordinateur connu</span>
                    <!-- ###BEGIN###{ComputerSelector-Local} -->
                    <div style="margin:4px">Commencez par <a onclick="addComputer()" style="cursor:pointer"><u>ajouter</u></a> ordinateurs ou glisser-déposer<br>un fichier de liste d'ordinateurs dans cette fenêtre.</div>
                    <!-- ###END###{ComputerSelector-Local} -->
                </div>
                <div id="id_computerList" style="font-size:20px"></div>
            </div>
        <div id="id_computerDetailsParent" style="position:fixed;top:96px;width:300px;right:0;bottom:0">
            <div id="id_computerDetails" style="font-size:16px;margin:4px"></div>
        </div>
        <!-- ###END###{ComputerSelectorToolbar} -->
        <!-- ###BEGIN###{!ComputerSelectorToolbar} -->
        <div id="id_computerListParent" style="position:fixed;top:69px;left:0;right:300px;bottom:0;overflow-y:scroll" cm="Add&nbsp;Computer...#addComputer()">
            <div id="id_noKnownComputers" style="text-align:center;margin-top:36px;color:gray">
                <span style="font-size:20px">Aucun ordinateur connu</span>
                <!-- ###BEGIN###{ComputerSelector-Local} -->
                <div style="margin:4px">Commencez par <a onclick="addComputer()" style="cursor:pointer"><u>ajouter</u></a> ordinateurs ou glisser-déposer<br>un fichier de liste d'ordinateurs dans cette fenêtre.</div>
                <!-- ###END###{ComputerSelector-Local} -->
            </div>
            <div id="id_computerList" style="font-size:20px"></div>
        </div>
        <div id="id_computerDetailsParent" style="position:fixed;top:69px;width:300px;right:0;bottom:0;background-color:white">
            <div id="id_computerDetails" style="font-size:16px;margin:8px"></div>
        </div>
        <!-- ###END###{!ComputerSelectorToolbar} -->
    </div>
    <div id="id_computerSelectorMenu" style="background-color:#EEEEEE;display:none;position:absolute;left:0;top:94px;width:200px;padding:3px;z-index:1000;box-shadow:5px 5px 5px #888888;border:1px solid gray">
        <div class="menuitem" onclick="toolmenuclick(101)"><span id="id_menuitem1">• </span>Gestion d'ordinateur</div>
        <!-- ###BEGIN###{CertificateManager} -->
        <div class="menuitem" onclick="toolmenuclick(103)"><span id="id_menuitem3" style="display:none">• </span>Gestionnaire de certificats</div>
        <!-- ###END###{CertificateManager} -->
        <!-- ###BEGIN###{USBSetup} -->
        <div class="menuitem" onclick="toolmenuclick(102)"><span id="id_menuitem2" style="display:none">• </span>Éditeur USB Setup.bin</div>
        <!-- ###END###{USBSetup} -->
        <!-- ###BEGIN###{SessionRecording} -->
        <div class="menuitem" onclick="toolmenuclick(104)"><span id="id_menuitem4" style="display:none">• </span>Lecteur de session</div>
        <!-- ###END###{SessionRecording} -->
    </div>
    <!-- ###END###{ComputerSelector} -->
    <!-- ###BEGIN###{Mode-LMS} -->
    <div id="id_computerSelectorMenu" style="background-color:#EEEEEE;display:none;position:absolute;left:0;top:94px;width:200px;padding:3px;z-index:1000;box-shadow:5px 5px 5px #888888;border:1px solid gray">
        <div class="menuitem" onclick="toolmenuclick(101)"><span id="id_menuitem1">• </span>Computer Configuration</div>
        <!-- ###BEGIN###{USBSetup} -->
        <div class="menuitem" onclick="toolmenuclick(102)"><span id="id_menuitem2" style="display:none">• </span>Éditeur USB Setup.bin</div>
        <!-- ###END###{USBSetup} -->
    </div>
    <!-- ###END###{Mode-LMS} -->
    <!-- ###BEGIN###{USBSetup} -->
    <div id="id_usbSetupPanel" class="fullcell" style="display:none">
        <!-- ###BEGIN###{ComputerSelectorToolbar} -->
        <table style="background-color:#808080;width:100%">
            <tbody><tr>
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <td style="width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </td>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <td>
                    <input type="button" value="Nouveau..." onclick="usb_newSetupBin()">
                    <input type="button" value="Ouvert..." onclick="usb_openSetupBin()">
                    <!-- ###BEGIN###{FileSaver} -->
                    <input id="id_saveSetupBin" type="button" value="Sauver..." onclick="usb_saveSetupBin()">
                    <!-- ###END###{FileSaver} -->
                </td>
            </tr>
        </tbody></table>
        <div id="id_usbSetupPanel2" style="position:fixed;overflow-y:scroll;left:0;right:0;bottom:0;top:96px">
            <div id="id_StartupScreen" style="width:100%;text-align:center;color:gray;margin-top:36px">
                <span style="font-size:20px">Intel<sup style="font-size:10px">®</sup> AMT USB Setup.bin Manager</span>
                <div style="margin:4px">Commencez par <a onclick="usb_newSetupBin()" style="cursor:pointer"><u>création</u></a> un nouveau fichier, <a onclick="usb_openSetupBin()" style="cursor:pointer"><u>ouverture</u></a> un existant<br>ou faites glisser et déposez un fichier setup.bin dans cette fenêtre.</div>
            </div>
            <div id="id_SetupBinArea" style="margin:10px"></div>
        </div>
        <!-- ###END###{ComputerSelectorToolbar} -->
        <!-- ###BEGIN###{!ComputerSelectorToolbar} -->
        <div style="position:fixed;overflow-y:scroll;left:0;right:0;bottom:0;top:69px">
            <div id="id_StartupScreen" style="width:100%;text-align:center;color:gray;margin-top:36px">
                <span style="font-size:20px">Intel<sup style="font-size:10px">®</sup> AMT USB Setup.bin Manager</span>
                <div style="margin:4px">Commencez par <a onclick="usb_newSetupBin()" style="cursor:pointer"><u>création</u></a> un nouveau fichier, <a onclick="usb_openSetupBin()" style="cursor:pointer"><u>ouverture</u></a> un existant<br>ou faites glisser et déposez un fichier setup.bin dans cette fenêtre.</div>
            </div>
            <div id="id_SetupBinArea" style="margin:10px"></div>
        </div>
        <!-- ###END###{!ComputerSelectorToolbar} -->
    </div>
    <!-- ###END###{USBSetup} -->
    <!-- ###BEGIN###{CertificateManager} -->
    <div id="id_certManagerPanel" class="fullcell" style="display:none">
        <!-- ###BEGIN###{ComputerSelectorToolbar} -->
        <table style="background-color:#808080;width:100%">
            <tbody><tr>
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <td style="width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </td>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <td>
                    <input type="button" value="Créer un certificat racine ..." onclick="cert_createNew()">
                    <input id="IssueCertButton" type="button" value="Délivrer un certificat ..." onclick="cert_issueNew()">
                    <input type="button" value="Importer un certificat ..." onclick="cert_importCert()">
                </td>
            </tr>
        </tbody></table>
        <div id="id_certManagerPanel2" style="position:fixed;overflow-y:scroll;left:0;right:0;bottom:0;top:96px">
            <div id="id_certStartScreen" style="width:100%;text-align:center;color:gray;margin-top:36px">
                <span style="font-size:20px">Gestionnaire de certificats</span>
                <div style="margin:4px">Les certificats jouent un rôle important dans toutes sortes de tâches de sécurité Intel® AMT: authentification réseau TLS,<br>Configuration de l'ACEI, signature du journal d'audit et plus encore. Utilisez ce panneau pour créer et gérer votre certificat de console.</div>
            </div>
            <div id="id_certManagerMainArea" style="font-size:20px"></div>
            <!-- ###BEGIN###{Mode-NodeWebkit} -->
            <input id="certOpenFile" type="file" style="display:none" accept=".cer;*.pfx;*.p12;*.pem;*.crt">
            <!-- ###END###{Mode-NodeWebkit} -->
        </div>
        <!-- ###END###{ComputerSelectorToolbar} -->
        <!-- ###BEGIN###{!ComputerSelectorToolbar} -->
        <div style="position:fixed;overflow-y:scroll;left:0;right:0;bottom:0;top:95px">
            <div id="id_certStartScreen" style="width:100%;text-align:center;color:gray;margin-top:36px">
                <span style="font-size:20px">Gestionnaire de certificats</span>
                <div style="margin:4px">Les certificats jouent un rôle important dans toutes sortes de tâches de sécurité Intel® AMT: authentification réseau TLS,<br>Configuration de l'ACEI, signature du journal d'audit et plus encore. Utilisez ce panneau pour créer et gérer votre certificat de console.</div>
            </div>
            <div id="id_certManagerMainArea" style="margin:10px"></div>
        </div>
        <!-- ###END###{!ComputerSelectorToolbar} -->
    </div>
    <!-- ###END###{CertificateManager} -->
    <!-- ###BEGIN###{SessionRecording} -->
    <div id="id_sessionPlayerPanel" class="fullcell" style="display:none">
        <table style="background-color:#808080;width:100%">
            <tbody><tr>
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <td style="width:26px;cursor:pointer" onclick="toolmenuclick(0)">
                    <span style="font-size:16px">&nbsp;☰</span>
                </td>
                <!-- ###END###{!Mode-NodeWebkit} -->
                <td>
                    <div style="float:right">
                        <input id="srec_toggleviewmode" type="button" value="Basculer le mode d'affichage" style="display:none" onclick="srec_toggleAspectRatio(1)">
                    </div>
                    <input type="button" id="srec_OpenFileButton" value="Fichier ouvert..." onclick="srec_openfile()">
                    <span id="srec_deskstatus" style="margin-left:4px"></span>
                </td>
            </tr>
        </tbody></table>
        <div style="overflow:hidden">
            <div id="srec_deskarea0">
                <div id="srec_deskarea2" style="height:2px">
                    <div style="background-color:gray"><div id="srec_progressbar" style="height:2px;width:0%;background-color:red"></div></div>
                </div>
                <div id="srec_deskarea3x" style="position:relative;max-height:calc(100vh - 123px);height:calc(100vh - 123px)" onclick="srec_togglePause()">
                    <div id="srec_metadatadiv" style="padding:20px;color:lightgrey;text-align:left;display:none"></div>
                    <div id="srec_DeskParent" style="width:100%;height:100%;background-color:black;display:none">
                        <canvas id="srec_Desk" width="640" height="480"></canvas>
                    </div>
                    <div id="srec_TermParent" style="position:absolute;top:0;height:100%;width:100%;background-color:black;display:none">
                        <div><pre id="srec_Term"></pre></div>
                    </div>
                    <!--<div id=srec_p11DeskConsoleMsg style="display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick=clearConsoleMsg()></div>-->
                </div>
                <div id="srec_deskarea4" style="padding-top:2px;padding-bottom:2px;background:#C0C0C0">
                    <div style="float:right;text-align:right;padding-right:4px">
                        <div id="srec_timespan" style="padding-top:4px;padding-right:4px">00:00:00</div>
                    </div>
                    <div>
                        &nbsp;
                        <input id="srec_PlayButton" type="button" value="Jouer" disabled="disabled" onclick="srec_play()">
                        <input id="srec_PauseButton" type="button" value="Pause" disabled="disabled" onclick="srec_pause()">
                        <input id="srec_RestartButton" type="button" value="Redémarrer" disabled="disabled" onclick="srec_restart()">
                        <select id="srec_PlaySpeed" onchange="this.blur();">
                            <option value="4">1/4 vitesse</option>
                            <option value="2">1/2 vitesse</option>
                            <option value="1" selected="">Vitesse normale</option>
                            <option value="0.5">2x vitesse</option>
                            <option value="0.25">4x vitesse</option>
                            <option value="0.1">10x vitesse</option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- ###END###{SessionRecording} -->
    <div id="id_mainview" style="height:100%;display:none">
        <div id="id_leftbar" class="navbar">
            <!-- ###BEGIN###{Mode-NodeWebkit} -->
            <div id="tlsNotification1" style="text-align:center;padding-top:8px;color:darkblue;cursor:pointer;display:none" onclick="showTlsCert(1)"><img src="images/lock.gif"> TLS sécurisé</div>
            <div id="tlsNotification2" style="text-align:center;padding-top:8px;color:darkblue;cursor:pointer;display:none" onclick="showTlsCert(1)"><img src="images/lock.gif"> TLS sécurisé (épinglé)</div>
            <div id="tlsNotification3" style="text-align:center;padding-top:8px;color:darkblue;cursor:pointer;display:none" onclick="showTlsCert(1)"><img src="images/lock.gif"> TLS (non approuvé)</div>
            <div id="tlsNotification4" style="text-align:center;padding-top:8px;color:darkblue;cursor:pointer;display:none;color:red" onclick="switchToTls()"><img src="images/unlock.gif"> Passer à TLS</div>
            <!-- ###END###{Mode-NodeWebkit} -->
            <!-- ###BEGIN###{ComputerSelector} -->
            <div style="padding:8px">
                <input type="button" id="disconnectButton" value="Déconnecter" onkeypress="return false" onkeydown="return false" onclick="disconnect()" style="width:138px">
            </div>
            <!-- ###END###{ComputerSelector} -->
            <!-- ###BEGIN###{Mode-LMS} -->
            <div style="padding:8px">
                <input type="button" id="disconnectButton" value="Déconnecter" onkeypress="return false" onkeydown="return false" onclick="disconnect()" style="width:138px">
            </div>
            <!-- ###END###{Mode-LMS} -->
            <!-- ###BEGIN###{Mode-Firmware} -->
            <br>
            <!-- ###END###{Mode-Firmware} -->
            <!-- ###BEGIN###{Mode-MeshCentral2} -->
            <br>
            <!-- ###END###{Mode-MeshCentral2} -->
            <p id="go1" class="nav1" onclick="go(1)"><a>État du système</a></p>
            <!-- ###BEGIN###{Desktop} -->
            <p id="go14" class="nav1" onclick="go(14)"><a>Bureau à distance</a></p>
            <!-- ###BEGIN###{DesktopInbandFiles} -->
            <p id="go24" class="nav1" onclick="go(24)">&nbsp;&nbsp;<a>Des dossiers</a></p>
            <!-- ###END###{DesktopInbandFiles} -->
            <!-- ###END###{Desktop} -->
            <!-- ###BEGIN###{Terminal} -->
            <p id="go13" class="nav1" onclick="go(13)"><a>Série sur LAN</a></p>
            <!-- ###END###{Terminal} -->
            <!-- ###BEGIN###{HardwareInfo} -->
            <p id="go2" class="nav1" onclick="go(2)"><a>Informations matériel</a></p>
            <!-- ###END###{HardwareInfo} -->
            <!-- ###BEGIN###{EventLog} -->
            <p id="go6" class="nav1" onclick="go(6)"><a>Journal des événements</a></p>
            <!-- ###END###{EventLog} -->
            <!-- ###BEGIN###{AuditLog} -->
            <p id="go15" class="nav1" onclick="go(15)"><a>Journal d'audit</a></p>
            <!-- ###END###{AuditLog} -->
            <!-- ###BEGIN###{Storage} -->
            <p id="go21" class="nav1" onclick="go(21)"><a>Espace de rangement</a></p>
            <!-- ###END###{Storage} -->
            <!-- ###BEGIN###{NetworkSettings} -->
            <p id="go8" class="nav1" onclick="go(8)"><a>Paramètres réseau</a></p>
            <!-- ###END###{NetworkSettings} -->
            <!-- ###BEGIN###{RemoteAccess} -->
            <p id="go17" class="nav1" onclick="go(17)"><a>Paramètres Internet</a></p>
            <!-- ###END###{RemoteAccess} -->
            <!-- ###BEGIN###{Certificates} -->
            <p id="go16" class="nav1" onclick="go(16)"><a>Paramètres de sécurité</a></p>
            <!-- ###END###{Certificates} -->
            <!-- ###BEGIN###{AgentPresence} -->
            <p id="go19" class="nav1" onclick="go(19)"><a>Présence d'agent</a></p>
            <!-- ###END###{AgentPresence} -->
            <!-- ###BEGIN###{SystemDefense} -->
            <p id="go18" class="nav1" onclick="go(18)"><a>Défense du système</a></p>
            <!-- ###END###{SystemDefense} -->
            <p id="go11" class="nav1" onclick="go(11)"><a>Comptes utilisateur</a></p>
            <!-- ###BEGIN###{EventSubscriptions} -->
            <p id="go22" class="nav1" onclick="go(22)"><a>Abonnements</a></p>
            <!-- ###END###{EventSubscriptions} -->
            <!-- ###BEGIN###{Alarms} -->
            <p id="go23" class="nav1" onclick="go(23)"><a>Alarmes de réveil</a></p>
            <!-- ###END###{Alarms} -->
            <!-- ###BEGIN###{Scripting-Editor} -->
            <p id="go20" class="nav1" onclick="go(20)"><a>Éditeur de script</a></p>
            <!-- ###END###{Scripting-Editor} -->
            <!-- ###BEGIN###{WsmanBrowser} -->
            <p id="go12" class="nav1" onclick="go(12)"><a>Navigateur WSMAN</a></p>
            <!-- ###END###{WsmanBrowser} -->
            <!-- ###BEGIN###{Storage} -->
            <!-- ###BEGIN###{Mode-Firmware} -->
            <!-- <div id=storagelinks style=margin-top:4px></div> -->
            <!-- ###END###{Mode-Firmware} -->
            <!-- ###END###{Storage} -->
            <!-- ###BEGIN###{Look-ISDU} -->
            <img id="id_isdu-image1" src="images-isdu/TabConfig.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image2" src="images-isdu/TabConnection.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image3" src="images-isdu/TabDesktop.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image4" src="images-isdu/TabDiscovery.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image5" src="images-isdu/TabEvents.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image6" src="images-isdu/TabNetwork.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image7" src="images-isdu/TabPolicies.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image8" src="images-isdu/TabRemote.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <!-- ###END###{Look-ISDU} -->
            <!-- ###BEGIN###{Look-BrandedCommander} -->
            <!-- ###BEGIN###{!Mode-Firmware} -->
            <img id="id_isdu-image1" src="images-BrandedCommander/TabConfig.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image2" src="images-BrandedCommander/TabConnection.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image3" src="images-BrandedCommander/TabDesktop.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image4" src="images-BrandedCommander/TabDiscovery.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image5" src="images-BrandedCommander/TabEvents.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image6" src="images-BrandedCommander/TabNetwork.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image7" src="images-BrandedCommander/TabPolicies.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <img id="id_isdu-image8" src="images-BrandedCommander/TabRemote.png" style="position:fixed;bottom:16px;left:32px;display:none">
            <!-- ###END###{!Mode-Firmware} -->
            <!-- ###END###{Look-BrandedCommander} -->
        </div>
        <div id="id_mainarea" class="maincell">
            <!-- ###BEGIN###{IDER} -->
            <div id="id_iderstatus" style="position:relative;height:21px;background:#8fac8d;padding:5px;margin-bottom:1px;display:none;z-index:1000">
                <div style="float:right">
                    <input id="IDERDiskMapButton" type="button" value="Carte du disque" onclick="iderToggleDiskMap()">
                    <input type="button" value="Arrêter la session IDE-R" onclick="iderStop()">
                </div>
                <div style="font-size:16px;padding-top:2px">&nbsp;<span id="id_iderstatusstr"></span></div>
                <div id="iderHeatmap" style="z-index:1000;position:absolute;top:31px;right:8px;border:1px solid black;box-shadow: 0px 0px 10px;border-radius:5px;padding:8px;width:600px;background-color:#99CC99;display:none">
                    <div id="floppyHeatMap" style="display:none">
                        <div id="floppyHeatMapText" style="margin:2px">Disquette, les blocs font 512 octets.</div>
                        <canvas id="floppyHeatMapCanvas" width="600" height="0"></canvas>
                    </div>
                    <div id="cdromHeatMap" style="display:none">
                        <div id="cdromHeatMapText" style="margin:2px">CD-ROM, les blocs font 2048 octets.</div>
                        <canvas id="cdromHeatMapCanvas" width="600" height="0"></canvas>
                    </div>
                </div>
            </div>
            <!-- ###END###{IDER} -->
            <!-- ###BEGIN###{Scripting} -->
            <div id="id_scriptstatus" style="height:21px;background:#8fac8d;padding:5px;margin-bottom:1px;display:none;overflow:hidden">
                <div style="float:right"><input type="button" value="Arrêter le script" onclick="script_Stop()"></div>
                <div style="font-size:16px;padding-top:2px;overflow:hidden">&nbsp;<b>Script en cours d'exécution</b><span style="overflow:hidden" id="id_scriptstatusstr"></span></div>
            </div>
            <!-- ###END###{Scripting} -->
            <!-- ###BEGIN###{VersionWarning} -->
            <div id="id_versionWarning" style="height:21px;background:#8fac8d;padding:5px;margin-bottom:1px;display:none">
                <div style="font-size:16px;float:right;cursor:pointer;padding-right:5px;padding-left:5px;padding-top:2px;font-size:15px" onclick="QV('id_versionWarning', false)">✖</div>
                <!-- ###BEGIN###{Mode-NodeWebkit} -->
                <div style="font-size:14px;padding-top:2px">&nbsp;<b>Le firmware de cet ordinateur doit être mis à jour,&nbsp;<a style="cursor:pointer" onclick="require('nw.gui').Shell.openExternal('https://security-center.intel.com/advisory.aspx?intelid=INTEL-SA-00075&amp;languageid=en-fr')"><u>veuillez vérifier ici</u></a>.</b></div>
                <!-- ###END###{Mode-NodeWebkit} -->
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <div style="font-size:14px;padding-top:2px">&nbsp;<b>Le firmware de cet ordinateur doit être mis à jour,&nbsp;<a style="cursor:pointer" href="https://security-center.intel.com/advisory.aspx?intelid=INTEL-SA-00075&amp;languageid=en-fr" rel="noreferrer noopener" target="_blank"><u>veuillez vérifier ici</u></a>.</b></div>
                <!-- ###END###{!Mode-NodeWebkit} -->
            </div>
            <!-- ###END###{VersionWarning} -->
            <!-- ###BEGIN###{Storage} -->
            <div id="id_mainarea_frame" style="width:100%;height:100%">
                <iframe id="id_StorageIFrame" style="width:100%;height:100%;border:0"></iframe>
            </div>
            <!-- ###END###{Storage} -->
            <div id="id_mainarea_pad" style="padding:8px;overflow-x:hidden">
                <div id="p0">
                    <h1>Chargement...</h1>
                </div>
                <div id="p1" style="display:none">
                    <h1>État du système</h1>
                    <span id="id_TableSysStatus"></span>
                </div>
                <!-- ###BEGIN###{HardwareInfo} -->
                <div id="p2" style="display:none">
                    <h1 style="margin-bottom:16px">Informations matériel</h1>
                    <span id="id_TableSysInfo"></span>
                </div>
                <!-- ###END###{HardwareInfo} -->
                <!-- ###BEGIN###{EventLog} -->
                <div id="p6" style="display:none">
                    <h1>Journal des événements</h1>
                    <span id="id_TableEventLog"></span>
                    <span id="id_TableEventLog2"></span>
                </div>
                <!-- ###END###{EventLog} -->
                <!-- ###BEGIN###{NetworkSettings} -->
                <div id="p8" style="display:none">
                    <h1>Paramètres réseau</h1>
                    <span id="id_TableNetworkSettingsSpan"></span>
                    <!-- ###BEGIN###{Wireless} -->
                    <span id="id_TableWifi2"></span>
                    <!-- ###END###{Wireless} -->
                    <!-- ###BEGIN###{NetAuth} -->
                    <span id="id_TableNetAuth"></span>
                    <!-- ###END###{NetAuth} -->
                </div>
                <!-- ###END###{NetworkSettings} -->
                <div id="p11" style="display:none">
                    <h1>Comptes utilisateur</h1>
                    <span id="id_TableUserAccounts"></span>
                </div>
                <!-- ###BEGIN###{WsmanBrowser} -->
                <div id="p12" style="display:none">
                    <h1>Navigateur WSMAN</h1>
                    <div>
                        <table class="log1" cellpadding="0" cellspacing="0" style="width:100%;border-radius:8px">
                            <tbody><tr>
                                <td>
                                    <div style="padding:4px">
                                        <select id="id_QuerySelect" multiple="multiple" style="width:100%;height:120px"></select>
                                    </div>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <input id="id_p12querybutton" type="button" value="Requete" style="margin: 4px" onclick="wsmanQuery()">
                                    <input type="button" value="Clair" style="margin: 4px" onclick="QH('id_wsresults', '')">
                                    <input id="idx_browserFilter" placeholder="Filtre" style="margin: 4px" onkeyup="wsmanFilter()">
                                </td>
                            </tr>
                        </tbody></table>
                    </div>
                    <br>
                    <div class="us" id="id_wsresults"></div>
                </div>
                <!-- ###END###{WsmanBrowser} -->
                <!-- ###BEGIN###{Terminal} -->
                <div id="p13" style="display:none;min-width:780px">
                    <h1>Terminal série sur LAN</h1>
                    <br>
                    <div id="id_p13warning1" style="max-width:100%;display:none;cursor:pointer;margin-bottom:5px" onclick="showFeaturesDlg()">
                        <div class="icon2" style="float:left;margin:7px"></div><div style="width:auto;border-radius:8px;padding:8px;background-color:lightsalmon">Le port de redirection Intel® AMT ou la fonction série sur LAN est désactivé<span id="id_p13warninga">, cliquez ici pour l'activer.</span></div>
                    </div>
                    <!-- ###BEGIN###{PowerControl} -->
                    <div id="id_p13warning2" style="max-width:100%;display:none;cursor:pointer;margin-bottom:5px" onclick="showPowerActionDlg()">
                        <div class="icon2" style="float:left;margin:7px"></div><div style="width:auto;border-radius:8px;padding:8px;background-color:lightsalmon">L'ordinateur distant n'est pas sous tension, cliquez ici pour lancer une commande d'alimentation.</div>
                    </div>
                    <!-- ###END###{PowerControl} -->
                    <table cellpadding="0" cellspacing="0" style="width:100%;padding:0px;padding:0px;margin-top:0px">
                        <tbody><tr>
                            <td style="padding-top:2px;padding-bottom:2px;background:#CCC">
                                <div style="float:right; text-align:right">
                                    <input onkeyup="sendTermInputKeys(event)" autocorrect="off" autocapitalize="off" style="opacity:0;width:0;height:0;font-size:1px" onblur="keyInputBlur()">
                                    <span id="id_p13power"></span>&nbsp;
                                    <!-- ###BEGIN###{Mode-MeshCentral2} -->
                                    <div id="termRecordIcon" title="Server is recording this session" style="display:none;float:right;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-right:4px"></div>
                                    <!-- ###END###{Mode-MeshCentral2} -->
                                    <!-- ###BEGIN###{PowerControl} -->
                                    <input type="button" onkeypress="return false" onkeydown="return false" class="cadbutton" value="Actions de puissance ..." onclick="showPowerActionDlg()" style="margin-right:3px">
                                    <!-- ###END###{PowerControl} -->
                                    <!-- ###BEGIN###{IDER} -->
                                    <!-- ###BEGIN###{Mode-MeshCentral2} -->
                                    <input type="button" id="idx_SIDER1" value="SIDER" title="Start server-side remote disk mount operation" onkeypress="return false" onkeydown="return false" onclick="iderServerStart()" style="margin-right:3px">
                                    <!-- ###END###{Mode-MeshCentral2} -->
                                    <input type="button" id="idx_IDER1" value="IDER" title="Démarrer l'opération de montage de disque à distance" onkeypress="return false" onkeydown="return false" onclick="iderStart(event)" style="margin-right:3px">
                                    <!-- ###END###{IDER} -->
                                    <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                                    <!-- ###BEGIN###{FileSaver} -->
                                    <input id="idx_terminalCaptureButton" type="button" onkeypress="return false" onkeydown="return false" class="cadbutton" value="Commencer la capture" title="Toggle start/stop of terminal capture, when stopping the content of the capture buffer will be saved to a file." onclick="terminalCaptureToggle(event)" style="margin-right:3px">
                                    <!-- ###END###{FileSaver} -->
                                    <!-- ###BEGIN###{TerminalReplay} -->
                                    <!-- <input id="idx_terminalReplayButton" type="button" onkeypress="return false" onkeydown="return false" class="cadbutton" value="Replay Capture" onclick="terminalReplay()" style="margin-right:3px"> -->
                                    <!-- ###END###{TerminalReplay} -->
                                    <!-- ###END###{!Mode-NodeWebkit} -->
                                </div>
                                <div>
                                    &nbsp;<input type="button" id="idx_connectbutton2" value="Relier" onclick="connectTerminal(event)" disabled="disabled">
                                    &nbsp;<span id="id_termstatus">Débranché.</span>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <td style="background:#000;text-align:center"><pre id="Term"></pre></td>
                        </tr>
                        <tr>
                            <td style="padding-top:2px;padding-bottom:2px;background:#CCC">
                                <div style="float:right;text-align:right">
                                    <input id="id_tcrbutton" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event);return false" class="bottombutton" value="CR + LF" title="Inverser ce que la touche retour enverra" onclick="termToggleCr();Q('id_tcrbutton').blur()">
                                    <!-- ###BEGIN###{TerminalSize} -->
                                    <input id="id_tsizebutton" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="80x25" title="Basculer la taille du terminal" onclick="termToggleSize();Q('id_tsizebutton').blur()">
                                    <!-- ###END###{TerminalSize} -->
                                    <input id="id_tfxkeysbutton" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event);return false" class="bottombutton" value="Intel (F10 = ESC + [OM)" title="Basculer le type d'émulation des touches F1 à F10" onclick="termToggleFx();Q('id_tfxkeysbutton').blur()">
                                    <!-- ###BEGIN###{Terminal-Enumation-All} -->
                                    <input id="id_ttypebutton" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event);return false" class="bottombutton" value="Ascii étendu" title="Basculer le type d'émulation de terminal" onclick="termToggleType();Q('id_ttypebutton').blur()">&nbsp;
                                    <!-- ###END###{Terminal-Enumation-All} -->
                                </div>
                                <div>
                                    <!-- ###BEGIN###{Mode-NodeWebkit} -->
                                    <input id="id_toolbtncc" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="Ctl-C" onclick="termSendKey(3);Q('id_toolbtncc').blur()">
                                    <input id="id_toolbtncx" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="Ctl-X" onclick="termSendKey(24);Q('id_toolbtncx').blur()">
                                    <input id="id_toolbtnes" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="ESC" onclick="termSendKey(27);Q('id_toolbtnes').blur()">
                                    <input id="id_toolbtnbs" type="button" onkeypress="return false" onkeydown="if (event.keyCode == 13) handleKeyPress(event); return false" class="bottombutton" value="Retour arrière" onclick="termSendKey(8);Q('id_toolbtnbs').blur()">
                                    <!-- ###END###{Mode-NodeWebkit} -->
                                    <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                                    <span id="termkeysspan">
                                        <select style="margin-left:6px" id="termkeys">
                                            <option value="3">Ctrl-C</option>
                                            <option value="24">Ctrl-X</option>
                                            <option value="27">ESC</option>
                                            <option value="8">Retour arrière</option>
                                            <option value="1001">F1</option>
                                            <option value="1002">F2</option>
                                            <option value="1003">F3</option>
                                            <option value="1004">F4</option>
                                            <option value="1005">F5</option>
                                            <option value="1006">F6</option>
                                            <option value="1007">F7</option>
                                            <option value="1008">F8</option>
                                            <option value="1009">F9</option>
                                            <option value="1010">F10</option>
                                            <option value="1011">F11</option>
                                            <option value="1012">F12</option>
                                        </select>
                                        <input id="TermWD" type="button" value="Envoyer" onkeypress="return false" onkeydown="return false" onclick="termSendKeys()">
                                        &nbsp;
                                    </span>
                                    <!-- ###END###{!Mode-NodeWebkit} -->
                                    <input id="id_tpastebutton" type="button" onkeypress="return false" onkeydown="return false" class="cadbutton" value="Pâte" disabled="disabled" onclick="setDialogMode(3,'Paste',3,termPaste)">
                                </div>
                            </td>
                        </tr>
                    </tbody></table>
                </div>
                <!-- ###END###{Terminal} -->
                <!-- ###BEGIN###{Desktop} -->
                <div id="p14" style="display:none;min-width:780px">
                    <div id="id_rdheader"><h1>Bureau à distance</h1><br></div>
                    <div id="id_p14warning1" style="max-width:100%;display:none;cursor:pointer;margin-bottom:5px" onclick="showFeaturesDlg()">
                        <div class="icon2" style="float:left;margin:7px"></div><div style="width:auto;border-radius:8px;padding:8px;background-color:lightsalmon">Le port de redirection Intel® AMT ou la fonctionnalité KVM est désactivé<span id="id_p14warninga">, cliquez ici pour l'activer.</span></div>
                    </div>
                    <!-- ###BEGIN###{PowerControl} -->
                    <div id="id_p14warning2" style="max-width:100%;display:none;cursor:pointer;margin-bottom:5px" onclick="showPowerActionDlg()">
                        <div class="icon2" style="float:left;margin:7px"></div><div style="width:auto;border-radius:8px;padding:8px;background-color:lightsalmon">L'ordinateur distant n'est pas sous tension, cliquez ici pour lancer une commande d'alimentation.</div>
                    </div>
                    <!-- ###END###{PowerControl} -->
                    <table cellpadding="0" cellspacing="0" style="width: 100%; padding: 0px; padding: 0px; margin-top: 0px">
                        <tbody><tr>
                            <td style="padding-top: 2px;padding-bottom:2px;background: #CCC">
                                <div style="float:right; text-align:right">
                                    <span id="id_p14power"></span>&nbsp;
                                    <div class="rb" title="Tourne à gauche" onclick="drotate(-1)">↺</div>
                                    <div class="rb" title="Tourner à droite" onclick="drotate(1)">↻</div>
                                    <!-- ###BEGIN###{Mode-MeshCentral2} -->
                                    <div id="deskRecordIcon" title="Server is recording this session" style="display:none;float:right;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-right:4px"></div>
                                    <!-- ###END###{Mode-MeshCentral2} -->
                                    <input id="idx_deskFullBtn" type="button" title="Basculer en mode plein écran" onkeypress="return false" onkeydown="return false" value="Plein" onclick="deskToggleFull()" style="margin-right:3px">
                                    <!-- ###BEGIN###{DesktopFocus} -->
                                    <input id="idx_deskFocusBtn" type="button" title="Basculer le mode de mise au point, lorsqu'il est actif, seule la région autour de la souris est mise à jour" onkeypress="return false" onkeydown="return false" value="Tout concentrer" onclick="deskToggleFocus()" style="margin-right:3px">
                                    <!-- ###END###{DesktopFocus} -->
                                    <!-- ###BEGIN###{FileSaver} -->
                                    <!-- ###BEGIN###{!DesktopRecorder} -->
                                    <input id="idx_deskSaveBtn" type="button" title="Enregistrer une capture d'écran du bureau distant" onkeypress="return false" onkeydown="return false" value="Sauver..." onclick="deskSaveImage()" style="margin-right:3px">
                                    <!-- ###END###{!DesktopRecorder} -->
                                    <!-- ###END###{FileSaver} -->
                                    <input type="button" value="Réglages..." title="Modifier les paramètres du bureau distant" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()" style="margin-right:3px">
                                    <!-- ###BEGIN###{IDER} -->
                                    <!-- ###BEGIN###{Mode-MeshCentral2} -->
                                    <input type="button" id="idx_SIDER2" value="SIDER" title="Start server-side remote disk mount operation" onkeypress="return false" onkeydown="return false" onclick="iderServerStart()" style="margin-right:3px">
                                    <!-- ###END###{Mode-MeshCentral2} -->
                                    <input type="button" id="idx_IDER2" value="IDER" title="Démarrer l'opération de montage de disque à distance" onkeypress="return false" onkeydown="return false" onclick="iderStart(event)" style="margin-right:3px">
                                    <!-- ###END###{IDER} -->
                                    <!-- ###BEGIN###{PowerControl} -->
                                    <input type="button" title="Modifier l'état d'alimentation de la machine distante" onkeypress="return false" onkeydown="return false" value="Actions de puissance ..." onclick="showPowerActionDlg()" style="margin-right:3px">
                                    <!-- ###END###{PowerControl} -->
                                </div>
                                <div>
                                    <div id="idx_deskFullBtn2" onclick="deskToggleFull()" style="float:left;cursor:pointer;font-size:15px;display:none">&nbsp;✖</div>
                                    &nbsp;<input type="button" id="idx_connectbutton1" value="Relier" onclick="connectDesktopButton(event)" onkeypress="return false" onkeydown="return false" disabled="disabled">
                                    &nbsp;<span id="id_deskstatus">Débranché.</span>
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <td id="id_DeskParent" style="background:black;text-align:center;position:relative">
                                <!-- ###BEGIN###{DesktopFocus} -->
                                <div id="DeskFocus" style="color:transparent;border:3px dotted rgba(255,0,0,.2);position:absolute;border-radius:5px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)"></div>
                                <!-- ###END###{DesktopFocus} -->
                                <!-- ###BEGIN###{DesktopInband} -->
                                <canvas id="Desk" width="640" height="400" style="-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)" onwheel="dmousewheel(event)" moz-opaque=""></canvas>
                                <!-- ###END###{DesktopInband} -->
                                <!-- ###BEGIN###{!DesktopInband} -->
                                <canvas id="Desk" width="640" height="400" style="-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)" moz-opaque=""></canvas>
                                <!-- ###END###{!DesktopInband} -->
                            </td>
                        </tr>
                        <tr>
                            <td style="padding-top:2px;padding-bottom:2px;background:#CCC">
                                <!--
                        <div style="float:right; text-align:right">
                            <select id="specialkeylist" onkeypress="return false"></select>
                            <input id="specialkeylistinput" type="button" onkeypress="return false" class="bottombutton" value="Send" onclick="sendSpecialKey()">&nbsp;
                        </div>
                        -->
                                <!-- ###BEGIN###{DesktopClipboard} -->
                                <input id="id_DeskKvmClipButton" value="Presse-papiers" type="button" style="float:right;display:none" onclick="deskClipboard()">
                                <!-- ###END###{DesktopClipboard} -->
                                <!-- ###BEGIN###{FileSaver} -->
                                <!-- ###BEGIN###{DesktopRecorder} -->
                                <div id="id_DeskRecorderTools" style="float:right">
                                    <div id="DeskRecordButton" class="videoIcon" title="Enregistrer une session de bureau à distance dans un fichier" onclick="deskRecordSession()"></div>
                                    <div id="DeskSaveImageButton" class="cameraIcon" title="Enregistrer une capture d'écran du bureau distant" onclick="deskSaveImage()"></div>
                                </div>
                                <!-- ###END###{DesktopRecorder} -->
                                <!-- ###END###{FileSaver} -->
                                <!-- ###BEGIN###{Desktop-Multi} -->
                                <div id="id_DeskScreenSelector" style="float:right"></div>
                                <!-- ###END###{Desktop-Multi} -->
                                <div>
                                    &nbsp;
                                    <span id="deskkeysspan">
                                        <select style="margin-left:6px" id="deskkeys">
                                            <option value="0">Gagner</option>
                                            <option value="1">Win + Down</option>
                                            <option value="2">Gagnez +</option>
                                            <option value="3">Win + L</option>
                                            <option value="4">Win + M</option>
                                            <option value="20">Win + R</option>
                                            <option value="23">Gagner + Gauche</option>
                                            <option value="24">Win + Right</option>
                                            <option value="5">Maj + Win + M</option>
                                            <option value="19">Alt-Tab</option>
                                            <option value="21">Alt-F4</option>
                                            <option value="22">Ctrl-W</option>
                                            <option value="6">F1</option>
                                            <option value="7">F2</option>
                                            <option value="8">F3</option>
                                            <option value="9">F4</option>
                                            <option value="10">F5</option>
                                            <option value="11">F6</option>
                                            <option value="12">F7</option>
                                            <option value="13">F8</option>
                                            <option value="14">F9</option>
                                            <option value="15">F10</option>
                                            <option value="16">F11</option>
                                            <option value="17">F12</option>
                                            <option value="25">Enter</option>
                                            <!-- <option value=18>LS+LA+PrtSc</option> -->
                                        </select>
                                        <input id="DeskWD" type="button" value="Envoyer" onkeypress="return false" onkeydown="return false" onclick="deskSendKeys()">
                                        &nbsp;
                                    </span>
                                    <input id="id_DeskCAD" type="button" value="Ctrl-Alt-Suppr" onkeypress="return false" onkeydown="return false" onclick="sendCAD()">&nbsp;
                                    <!-- ###BEGIN###{DesktopType} -->
                                    <input id="id_DeskType" type="button" value="Type" onkeypress="return false" onkeydown="return false" onclick="deskShowTypeDialog()">&nbsp;
                                    <!-- ###END###{DesktopType} -->
                                    <span id="id_DeskSBspan"><input id="id_DeskSB" type="checkbox"> Écran blanc&nbsp;</span>
                                    <span id="id_DeskVOspan"><input id="id_DeskVO" type="checkbox"> Voir seulement&nbsp;</span>
                                </div>
                            </td>
                        </tr>
                    </tbody></table>
                </div>
                <!-- ###END###{Desktop} -->
                <!-- ###BEGIN###{AuditLog} -->
                <div id="p15" style="display:none">
                    <span id="id_TableAuditLog1"></span>
                    <h1>Journal d'audit</h1>
                    <span id="id_TableAuditLog2"></span>
                </div>
                <!-- ###END###{AuditLog} -->
                <!-- ###BEGIN###{Certificates} -->
                <div id="p16" style="display:none">
                    <h1>Paramètres de sécurité</h1>
                    <span id="id_TableCerts"></span>
                </div>
                <!-- ###END###{Certificates} -->
                <!-- ###BEGIN###{RemoteAccess} -->
                <div id="p17" style="display:none">
                    <h1>Paramètres Internet</h1>
                    <span id="id_TableRemoteAccess"></span>
                </div>
                <!-- ###END###{RemoteAccess} -->
                <!-- ###BEGIN###{SystemDefense} -->
                <div id="p18" style="display:none">
                    <h1>Défense du système</h1>
                    <span id="id_TableSystemDefense"></span>
                </div>
                <!-- ###END###{SystemDefense} -->
                <!-- ###BEGIN###{AgentPresence} -->
                <div id="p19" style="display:none">
                    <h1>Présence d'agent</h1>
                    <span id="id_TableSystemAgentPresence"></span>
                </div>
                <!-- ###END###{AgentPresence} -->
                <!-- ###BEGIN###{Scripting-Editor} -->
                <div id="p20" style="display:none">
                    <h1>Éditeur de script</h1>
                    <div class="log1" style="padding:5px;border-radius:5px">
                        <div id="EditScriptStatus" style="float:right;font-weight:bold;padding:5px">Arrêté</div>
                        <div>
                            <input type="button" value="Editeur de vues" title="Passer à la vue de l'éditeur de ligne de script" id="viewEditorButton" onclick="scriptViewButton(0)">
                            <input type="button" value="Générateur de vues" title="Passer à la vue de l'éditeur de blocs" id="viewBuilderButton" onclick="scriptViewButton(1)">
                            <input type="button" value="Nouveau..." title="Effacer l'éditeur de script" onclick="script_newScriptDlg()">
                            <input type="button" value="Charge..." title="Charger un script à partir d'un fichier" onclick="script_runScriptDlg()">
                            <!-- ###BEGIN###{FileSaver} -->
                            <input type="button" value="Sauver..." title="Enregistrer un script dans un fichier" onclick="script_saveScript(event)">
                            <!-- ###END###{FileSaver} -->
                            <input type="button" value="Redémarrer" title="Compilez le script et préparez-vous à l'exécuter dès le début" onclick="resetScriptButton()">
                            <input type="button" value="Continuer" title="Exécutez le script à partir du point d'exécution actuel" onclick="runScriptButton()">
                            <input type="button" value="Pause" title="Suspendre l'exécution du script" onclick="breakScriptButton()">
                            <input type="button" value="Étape" title="Exécutez une étape du script" onclick="stepScriptButton()">
                        </div>
                    </div>
                    <div id="scriptbuilder" style="display:none">
                        <h2>Générateur de scripts</h2>
                        <div style="padding:0;margin:0">
                            <div style="width:250px;height:400px;float:left;padding:0;margin:0;padding-right:3px">
                                <input id="blockfilter" style="width:inherit;height:24px;padding:0;margin:0;border:1px solid gray;margin-bottom:1px" placeholder="Blocs filtrants ..." onkeyup="script_fonfilterchanged()">
                                <div id="blocks" style="width:inherit;height:373px;border:1px solid gray;overflow-y:scroll;padding:0;margin:0"></div>
                            </div>
                            <div id="scriptblocks" style="width:auto;height:400px;padding:0;margin:0;border:1px solid gray;overflow-y:scroll" ondrop="script_fondrop(event, this)" onclick="script_fonclick(event)"></div>
                        </div>
                    </div>
                    <div id="scripteditor">
                        <h2>Scénario</h2>
                        <textarea id="scriptarea" style="width:100%;height:176px;resize:vertical;margin:0;padding:0;font-family:Arial,Helvetica,sans-serif" spellcheck="false"></textarea>
                        <div style="display:none">
                            <br><h2>Script compilé</h2>
                            <textarea id="compiledarea" style="width:100%;height:16px;resize:vertical;margin:0;padding:0" spellcheck="false"></textarea>
                            <br>
                        </div>
                        <h2>Variables</h2>
                        <div id="variables" style="width:100%;height:200px;resize:vertical;border:1px solid gray;overflow:scroll;margin:0;padding:0;user-select:text;-webkit-user-select:text;-khtml-user-select:text;-moz-user-select:text;-ms-user-select:text"></div>
                    </div>
                    <h2>Console</h2>
                    <textarea id="console" style="width:100%;height:80px;resize:vertical;margin:0;padding:0;user-select:text;-webkit-user-select:text;-khtml-user-select:text;-moz-user-select:text;-ms-user-select:text" readonly=""></textarea>
                </div>
                <!-- ###END###{Scripting-Editor} -->
                <!-- ###BEGIN###{Storage} -->
                <div id="p21" style="display:none">
                    <h1>Espace de rangement</h1>
                    <span id="id_TableSystemStorage"></span>
                </div>
                <!-- ###END###{Storage} -->
                <!-- ###BEGIN###{EventSubscriptions} -->
                <div id="p22" style="display:none">
                    <h1>Abonnements aux événements</h1>
                    <span id="id_TableEventSubscriptions"></span>
                </div>
                <!-- ###END###{EventSubscriptions} -->
                <!-- ###BEGIN###{Alarms} -->
                <div id="p23" style="display:none">
                    <h1>Alarmes de réveil</h1>
                    <span id="id_TableAlarm"></span>
                </div>
                <!-- ###END###{Alarms} -->
                <!-- ###BEGIN###{DesktopInbandFiles} -->
                <div id="p24" style="display:none;position:absolute;top:0px;bottom:0px;left:8px;right:24px">
                    <h1>Des dossiers</h1><br>
                    <table id="p24toolbar" style="width:100%;position:absolute;top:35px" cellpadding="0" cellspacing="0">
                        <tbody><tr>
                            <td style="width:100%;background-color:#d3d9d6;text-align:left;padding:4px" valign="bottom">
                                <div id="p24rightOfButtons" style="float:right;margin-top:3px"></div>
                                <div>
                                    <input type="button" id="p24FolderUp" disabled="disabled" onclick="p24folderup()" value="En haut">&nbsp;
                                    <input type="button" id="p24SelectAllButton" disabled="disabled" onclick="p24selectallfile()" value="Tout sélectionner" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24RenameFileButton" disabled="disabled" value="Renommer" onclick="p24renamefile()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24DeleteFileButton" disabled="disabled" value="Supprimer" onclick="p24deletefile()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24NewFolderButton" disabled="disabled" value="Nouveau dossier" onclick="p24createfolder()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24UploadButton" disabled="disabled" value="Télécharger" onclick="p24uploadFile()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24CutButton" disabled="disabled" value="Couper" onclick="p24copyFile(1)" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24CopyButton" disabled="disabled" value="Copie" onclick="p24copyFile(0)" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24PasteButton" disabled="disabled" value="Pâte" onclick="p24pasteFile()" onkeypress="return false" onkeydown="return false">&nbsp;
                                    <input type="button" id="p24RefreshButton" disabled="disabled" value="Rafraîchir" onclick="p24folderup(9999)" onkeypress="return false" onkeydown="return false">&nbsp;
                                </div>
                            </td>
                        </tr>
                        <tr>
                            <td style="background-color:#E4E9E7;height:28px">
                                <div style="float:right;margin-right:4px">
                                    <select id="p24sortdropdown" onchange="p24updateFiles()">
                                        <option value="1" selected="selected">Trier par nom</option>
                                        <option value="2">Trier par taille</option>
                                        <option value="3">Trier par date</option>
                                        <option value="4">Descendre par nom</option>
                                        <option value="5">Descendre par taille</option>
                                        <option value="6">Descendre par date</option>
                                    </select>
                                </div>
                                <div>&nbsp;&nbsp;<span id="p24currentpath"></span></div>
                            </td>
                        </tr>
                    </tbody></table>
                    <div id="p24filetable" style="width:100%;overflow:auto;-webkit-user-select:none;position:absolute;top:92px;bottom:30px">
                        <div id="p24bigok" style="width:256px;overflow:hidden;position:absolute;top:80px;width:100%;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>✓</b></div>
                        <div id="p24bigfail" style="width:256px;overflow:hidden;position:absolute;top:80px;width:100%;text-align:center;font-size:1600%;color:#AAAAAA;display:none"><b>✗</b></div>
                        <span id="p24files"></span>
                    </div>
                    <table id="p24toolbarBottom" style="width:100%;position:absolute;bottom:10px" cellpadding="0" cellspacing="0">
                        <tbody><tr><td style="text-align:left;padding:3px;text-align:center;background-color:#D3D9D6">&nbsp;<span id="p24bottomstatus"></span></td></tr>
                    </tbody></table>
                </div>
                <!-- ###END###{DesktopInbandFiles} -->
            </div>
        </div>
    </div>
    <!-- ###BEGIN###{Mode-MeshCentral2} -->
    <div id="dialog" style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial, Helvetica, sans-serif;border-radius:5px;position:fixed;overflow:hidden;top:75px;width:400px;max-height:550px;display:none">
    <!-- ###END###{Mode-MeshCentral2} -->
    <!-- ###BEGIN###{!Mode-MeshCentral2} -->
    <div id="dialog" style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial, Helvetica, sans-serif;border-radius:5px;position:fixed;top:160px;width:400px;display:none">
    <!-- ###END###{!Mode-MeshCentral2} -->
        <div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
            <div id="id_dialogclose" style="float:right;padding:1px;margin-right:5px;cursor:pointer;font-size:15px" onclick="setDialogMode()">✖</div>
            <div id="id_dialogtitle" style="padding:5px"></div>
            <div style="width:100%;margin:6px"></div>
        </div>
        <div style="margin-right:16px;margin-left:8px">
            <div id="dialog1" style="margin:auto;text-align:center;margin:3px">
                <div id="id_dialogMessage" style="padding:10px"></div>
            </div>
            <div id="dialog2" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="d2username" style="float:right;width:200px" onkeyup="updateAccountDialog()"><div>Nom d'utilisateur</div></div>
                <div style="height:26px"><input id="d2password1" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="updateAccountDialog()"><div>Mot de passe*</div></div>
                <div style="height:26px"><input id="d2password2" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="updateAccountDialog()"><div>Confirmez le mot de passe</div></div>
                <div id="id_d2permissions">
                    <div style="height:26px"><select id="d2permission" style="float:right;width:200px"><option value="0">Local</option><option value="1">Réseau</option><option value="2">Tout</option></select><div>Autorisation</div></div>
                    <div>Autorisations accordées</div>
                    <ul id="id_d2realms" style="list-style-type:none;height:100px;overflow:auto;width:100%;border: 1px solid #000;background-color:white;overflow-x:hidden;margin:0;padding:0"></ul>
                </div>
                <div style="font-size:10px"><br>* 8 caractères minimum avec majuscules, minuscules, 0-9 et l'un des! @ # $% ^ &amp; * () + -</div>
            </div>
            <!-- ###BEGIN###{Terminal} -->
            <div id="dialog3" style="margin:auto;text-align:center;margin:3px">
                <textarea id="d3pastetextarea" maxlength="4096" style="width:100%;height:200px;resize:none"></textarea>
            </div>
            <!-- ###END###{Terminal} -->
            <!-- ###BEGIN###{Mode-LMS} -->
            <div id="dialog4" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="d4username" placeholder="administrateur" style="float:right;width:200px" onkeyup="lmsUpdateLoginDialog(event, 1)"><div>Nom d'utilisateur</div></div>
                <div style="height:26px"><input id="d4password" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="lmsUpdateLoginDialog(event, 2)"><div>Mot de passe*</div></div>
                <div style="font-size:10px"><br>* 8 caractères minimum avec majuscules, minuscules, 0-9 et l'un des! @ # $% ^ &amp; * () + -</div>
            </div>
            <!-- ###END###{Mode-LMS} -->
            <!-- ###BEGIN###{ComputerSelector} -->
            <div id="dialog4" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="d4name" style="float:right;width:200px" onkeyup="updateComputerDialog()"><div>Nom familier</div></div>
                <div style="height:26px"><input id="d4tags" list="d4devGroups" style="float:right;width:200px" placeholder="Mon groupe"><div>Nom de groupe</div></div>
                <div style="height:26px"><input id="d4hostname" style="float:right;width:200px" onkeyup="updateComputerDialog()"><div>Nom d'hôte</div></div>
                <div style="height:26px"><select id="d4security" style="float:right;width:200px" onchange="updateComputerDialog()"><option value="0">Digeste / Aucun</option><option value="1">Digest / TLS</option><option value="2">Kerberos / Aucun</option><option value="3">Kerberos / TLS</option></select><div>Auth / Sécurité</div></div>
                <div id="d4digest">
                    <div style="height:26px"><input id="d4username" value="administrateur" style="float:right;width:200px" onkeyup="updateComputerDialog()"><div>Nom d'utilisateur</div></div>
                    <div style="height:26px"><input id="d4password" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="updateComputerDialog()"><div>Mot de passe*</div></div>
                    <div style="font-size:10px"><br>* 8 caractères minimum avec majuscules, minuscules, 0-9 et l'un des! @ # $% ^ &amp; * () + -</div>
                </div>
                <div id="d4kerb">
                    <div style="height:26px"><input id="d4kerberos" style="float:right;width:200px" onkeyup="updateComputerDialog()" placeholder="computer.domain.com:16992" title="Si ce champ est rempli, cette valeur sera utilisée pour demander le jeton Kerberos au lieu de host: port."><div>Demande de jeton facultative *</div></div>
                    <div style="font-size:10px"><br>* Nom d'hôte alternatif pour la demande de jeton Kerberos</div>
                </div>
                <datalist id="d4devGroups"></datalist>
            </div>
            <!-- ###END###{ComputerSelector} -->
            <div id="dialog5" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="d5actionSelect" style="float:right;width:200px"></select>
                    <div>Action de puissance</div>
                </div>
                <div>
                    <span style="color:red">Attention:</span> Certaines actions d'alimentation peuvent entraîner une perte de données et déconnecter les sessions de redirection du bureau, du terminal ou du disque.
                </div>
            </div>
            <div id="dialog6" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="d6ConsentText" style="float:right;width:200px" maxlength="6" onkeyup="consentChanged()" onkeypress="if (event.keyCode == 13) return dialogclose(1); else return numbersOnly(event)"><div>Code de consentement</div></div>
                <div style="height:26px"><select id="d6Display" onchange="changeConsentDisplay()" style="float:right;width:200px"><option value="0">Affichage principal</option><option value="1">Affichage secondaire</option><option id="d6ThirdDisplay" value="2" style="display:none">Troisième affichage</option></select><div>Affichage du consentement</div></div>
            </div>
            <!-- ###BEGIN###{Desktop} -->
            <div id="dialog7" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="idx_d7desktopmode" style="float:right;width:200px"></select>
                    <div>Encodage d'image</div>
                </div>
                <div id="d7decimationspan" style="height:26px">
                    <select id="d7decimation" style="float:right;width:200px"><option value="0">Don't set</option><option value="1">désactivé</option><option value="2">Automatic</option><option value="3">Activée</option></select>
                    <div>Downscaling</div>
                </div>
                <div style="height:80px">
                    <div style="float:right;border:1px solid #666;width:200px;height:80px;overflow-y:scroll;background-color:white">
                        <!-- ###BEGIN###{DesktopFocus} -->
                        <label><input type="checkbox" id="d7showfocus">Afficher l'outil de mise au point</label><br>
                        <!-- ###END###{DesktopFocus} -->
                        <label><input type="checkbox" id="d7showcursor">Afficher le curseur de la souris locale</label><br>
                        <label><input type="checkbox" id="d7showcad">Afficher Ctrl-Alt-Suppr</label><br>
                        <label><input type="checkbox" id="d7limitFrameRate">Taux de trame limite</label><br>
                        <label><input type="checkbox" id="d7noMouseRotate">Ne faites pas tourner la souris</label><br>
                        <label><input type="checkbox" id="d7kvmrmw">Reverse Mouse Wheel</label><br>
                    </div>
                    <div>Autres réglages</div>
                </div>
                <!-- ###BEGIN###{DesktopInband} -->
                <div id="d7softkvmsettings" style="display:none">
                    <h4 style="width:100%;border-bottom:1px solid gray">Logiciel KVM</h4>
                    <div style="margin:3px 0 3px 0">
                        <select id="d7bitmapquality" style="float:right;width:200px;height:20px" dir="rtl">
                            <option value="50">50%</option>
                            <option value="40">40%</option>
                            <option selected="selected" value="30">30%</option>
                            <option value="20">20%</option>
                            <option value="10">dix%</option>
                            <option value="5">5%</option>
                            <option value="1">1%</option>
                        </select>
                        <div style="height:20px">Qualité</div>
                    </div>
                    <div style="margin:3px 0 3px 0">
                        <select id="d7bitmapscaling" style="float:right;width:200px;height:20px" dir="rtl">
                            <option selected="selected" value="1024">100%</option>
                            <option value="896">87,5%</option>
                            <option value="768">75%</option>
                            <option value="640">62,5%</option>
                            <option value="512">50%</option>
                            <option value="384">37,5%</option>
                            <option value="256">25%</option>
                            <option value="128">12,5%</option>
                        </select>
                        <div style="height:20px">Mise à l'échelle</div>
                    </div>
                </div>
                <!-- ###END###{DesktopInband} -->
            </div>
            <!-- ###END###{Desktop} -->
            <!-- ###BEGIN###{!Mode-Firmware} -->
            <div id="dialog8" style="display:table;margin:3px">
                <div style="margin:3px 0 3px 0;padding-top:5px">
                    <input id="idx_d8username" value="administrateur" style="float:right;width:220px">
                    <div style="height:20px">Nom d'utilisateur</div>
                </div>
                <div style="margin:3px 0 3px 0">
                    <input id="idx_d8password" type="password" autocomplete="off" style="float:right;width:220px">
                    <div style="height:20px">Mot de passe</div>
                </div>
            </div>
            <!-- ###END###{!Mode-Firmware} -->
            <div id="dialog9" style="margin:auto;margin:3px">
                <label style="display:block"><input type="checkbox" id="idx_d9redir">Port de redirection</label>
                <label id="idx_d9kvm_div" style="display:block"><input type="checkbox" id="idx_d9kvm">Bureau à distance KVM</label>
                <label style="display:block"><input type="checkbox" id="idx_d9ider">IDE-Redirection<br></label>
                <label style="display:block"><input type="checkbox" id="idx_d9sol">Série sur LAN<br></label>
            </div>
            <div id="dialog10" style="margin:auto;margin:3px">
                <label><input type="radio" name="d10" id="idx_d10none" value="0">Non requis<br></label>
                <label><input type="radio" name="d10" id="idx_d10kvm" value="1">Requis pour KVM uniquement<br></label>
                <label><input type="radio" name="d10" id="idx_d10all" value="4294967295">Toujours requis<br></label>
            </div>
            <div id="dialog11" style="margin:auto;margin:3px">
                <div id="id_dialogOptions"></div>
            </div>
            <!-- ###BEGIN###{Wireless} -->
            <div id="dialog12" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px"><input id="idx_d12name" style="float:right;width:200px" maxlength="32" onkeyup="updateWifiDialog()" title="32 caractères maximum"><div title="32 caractères maximum">Nom de profil</div></div>
                <div style="height:26px"><input id="idx_d12ssid" style="float:right;width:200px" maxlength="32" onkeyup="updateWifiDialog()" title="32 caractères maximum"><div title="32 caractères maximum">SSID</div></div>
                <div style="height:26px">
                    <select id="idx_d12pri" style="float:right;width:200px" onclick="updateWifiDialog()"></select>
                    <div>Priorité</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d12auth" style="float:right;width:200px" onclick="updateWifiDialog()"></select>
                    <div>Authentification</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d12enc" style="float:right;width:200px" onclick="updateWifiDialog()">
                        <option id="id_d12e4" value="4">CCMP-AES</option>
                        <option id="id_d12e3" value="3">TKIP-RC4</option>
                        <!--<option id="id_d12e2" value="2">WEP</option>-->
                        <!--<option id="id_d12e5" value="5">None</option>-->
                    </select>
                    <div>Chiffrement</div>
                </div>
                <div id="idx_d12pass">
                    <div style="height:26px"><input id="idx_d12password1" type="password" style="float:right;width:200px" maxlength="63" onkeyup="updateWifiDialog()" title="Longueur entre 8 et 63 caractères"><div title="Longueur entre 8 et 63 caractères">Mot de passe*</div></div>
                    <div style="height:26px"><input id="idx_d12password2" type="password" style="float:right;width:200px" maxlength="63" onkeyup="updateWifiDialog()" title="Longueur entre 8 et 63 caractères"><div title="Longueur entre 8 et 63 caractères">Confirmez le mot de passe</div></div>
                </div>
                <!-- ###BEGIN###{NetAuth} -->
                <div id="idx_d12netauth" style="display:none">
                    <div id="idx_d12protocoldiv" style="height:26px">
                        <select id="idx_d12protocol" style="float:right;width:200px" onchange="updateNetAuth2Dialog(event)">
                            <option value="0" selected="selected">EAP-TLS</option>
                            <option value="1">EAP-TTLS/MSCHAPv2</option>
                            <option value="2">PEAPv0/EAP-MSCHAPv2</option>
                            <option value="3">PEAPv1/EAP-GTC</option>
                            <option value="4">EAP-FAST/MSCHAPv2</option>
                            <option value="5">EAP-FAST/GTC</option>
                            <option value="6">EAP-FAST/TLS</option>
                        </select>
                        <div>Protocole</div>
                    </div>
                    <div id="idx_d12servernamediv" style="height:26px"><input id="idx_d12servername" style="float:right;width:200px" maxlength="80" onkeyup="updateNetAuthDialog()" title="32 caractères maximum"><div title="32 caractères maximum">Server Name</div></div>
                    <div id="idx_d12servernamecomparediv" style="height:26px">
                        <select id="idx_d12servernamecompare" style="float:right;width:200px" onclick="updateNetAuth2Dialog()">
                            <option value="0" selected="selected">Full Name</option>
                            <option value="1">Domain Suffix</option>
                        </select>
                        <div>Server Name Compare</div>
                    </div>
                    <div id="idx_d12domaindiv" style="height:26px"><input id="idx_d12domain" style="float:right;width:200px" maxlength="128" onkeyup="updateNetAuth2Dialog()" title="Maximum 128 characters"><div title="Maximum 128 characters">Domain</div></div>
                    <div id="idx_d12usernamediv" style="height:26px"><input id="idx_d12username" style="float:right;width:200px" maxlength="128" onkeyup="updateNetAuth2Dialog()" title="Maximum 128 characters"><div title="Maximum 128 characters">Nom d'utilisateur</div></div>
                    <div id="idx_d12passworddiv" style="height:26px"><input id="idx_d12password" type="password" style="float:right;width:200px" maxlength="32" onkeyup="updateNetAuth2Dialog()" title="Maximum length is 32 characters"><div title="Maximum length is 32 characters">Mot de passe</div></div>
                    <div id="idx_d12roamingidentitydiv" style="height:26px"><input id="idx_d12roamingidentity" style="float:right;width:200px" maxlength="80" onkeyup="updateNetAuth2Dialog()" title="Maximum 80 characters"><div title="Maximum 80 characters">Roaming Identity</div></div>
                    <div id="idx_d12pacdiv" style="height:26px"><input id="idx_d12pac" style="float:right;width:200px" maxlength="256" onkeyup="updateNetAuth2Dialog()" title="Maximum 256 characters"><div title="Maximum 256 characters">Protected Access Credentials</div></div>
                    <div id="idx_d12pacpassworddiv" style="height:26px"><input id="idx_d12pacpassword" type="password" style="float:right;width:200px" maxlength="256" onkeyup="updateNetAuth2Dialog()" title="Maximum length is 256 characters"><div title="Maximum length is 256 characters">PAC Password</div></div>
                    <div id="idx_d12clientcertdiv" style="height:26px">
                        <select id="idx_d12clientcert" style="float:right;width:200px" onclick="updateNetAuth2Dialog()"></select>
                        <div>Client Certificate</div>
                    </div>
                    <div id="idx_d12servercertdiv" style="height:26px">
                        <select id="idx_d12servercert" style="float:right;width:200px" onclick="updateNetAuth2Dialog()"></select>
                        <div>Server Issuer Cert</div>
                    </div>
                    <div id="idx_d12activeins0div" style="height:26px">
                        <select id="idx_d12activeins0" style="float:right;width:200px" onclick="updateNetAuth2Dialog()">
                            <option value="1">Activée</option>
                            <option value="0">désactivé</option>
                        </select>
                        <div>Active in S0</div>
                    </div>
                </div>
                <!-- ###END###{NetAuth} -->
            </div>
            <!-- ###END###{Wireless} -->
            <!-- ###BEGIN###{USBSetup} -->
            <div id="dialog13" style="margin:auto;margin:3px">
                <label><input type="checkbox" id="d13valid">Enregistrement valide<br></label>
                <span id="d13ScrambledRecordSpan"><label><input type="checkbox" id="d13scramble">Record brouillé</label><br></span>
            </div>
            <div id="dialog14" style="margin:auto;margin:3px">
                <div style="height:26px">
                    <select id="idx_d14version" style="float:right;width:200px">
                        <option value="1">Version 1</option>
                        <option value="2">Version 2</option>
                        <option value="3">Version 3</option>
                        <option value="4">Version 4</option>
                    </select>
                    <div>Version de Setup.bin</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d14consume" style="float:right;width:200px">
                        <option value="1">Les enregistrements ne seront pas consommés</option>
                        <option value="0">Les enregistrements seront consommés</option>
                    </select>
                    <div>Record de consommation</div>
                </div>
            </div>
            <div id="dialog15" style="margin:auto;margin:3px">
                <input id="d15setupbinfile" type="file" style="width:100%" accept=".bin">
            </div>
            <div id="dialog16" style="margin:auto;margin:3px">
                <div style="height:26px">
                    <select id="d16type" style="float:right;width:260px" onchange="usb_ond16typechange()" onclick="usb_ond16typechange()" onscroll="usb_ond16typechange()" onkeydown="usb_ond16typechange()"></select>
                    <div>Type variable</div>
                </div>
                <div id="d16genericvalue" style="height:26px">
                    <select id="idx_d16value1" style="float:right;width:260px"></select>
                    <input id="idx_d16value2" style="float:right;width:260px;display:none">
                    <div>Valeur variable</div>
                </div>
                <div id="d16customvalue"></div>
            </div>
            <!-- ###END###{USBSetup} -->
            <!-- ###BEGIN###{ComputerSelector} -->
            <div id="dialog17" style="margin:auto;margin:3px">
                <input id="idx_d17computerlistfile" type="file" style="width:100%" accept=".json, .csv">
            </div>
            <div id="dialog18" style="margin:auto;margin:3px">
                <!-- ###BEGIN###{!Mode-NodeWebkit} -->
                <input id="idx_d18computerfilename" style="width:100%" value="computerlist.json">
                <!-- ###END###{!Mode-NodeWebkit} -->
                <!-- ###BEGIN###{Mode-NodeWebkit} -->
                <!-- <input id="idx_d18computersavefile" type="file" nwsaveas="computerlist.json" accept=".json"> -->
                <div style="text-align:left;height:26px;padding-top:6px">
                    <label><input id="d18usepassword" type="checkbox" style="float:left" onchange="saveComputerListUpdate()"><div>Utilisez le cryptage. Le fichier contiendra les informations d'identification Intel® AMT, l'enregistrement à l'aide d'un mot de passe peut aider à protéger ces données.</div></label>
                </div>
                <div id="d18showpassword" style="display:none;padding-top:16px">
                    <div style="height:26px"><input id="d18password1" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="saveComputerListUpdate()"><div>Mot de passe*</div></div>
                    <div style="height:26px"><input id="d18password2" type="password" autocomplete="off" style="float:right;width:200px" onkeyup="saveComputerListUpdate()"><div>Confirmez le mot de passe</div></div>
                    <div style="font-size:10px"><br>* 8 caractères minimum avec majuscules, minuscules, 0-9 et l'un des! @ # $% ^ &amp; * () + -</div>
                </div>
                <!-- ###END###{Mode-NodeWebkit} -->
            </div>
            <!-- ###END###{ComputerSelector} -->
            <!-- ###BEGIN###{FileSaver} -->
            <div id="dialog19" style="margin:auto;margin:3px">
                Cela enregistrera l'intégralité de l'état d'Intel® AMT pour cette machine dans un fichier. Les mots de passe ne seront pas enregistrés, mais certaines données sensibles peuvent être incluses.<br><br>
                <input id="idx_d19savestatefilename" style="width:100%" value="amtstate.json">
            </div>
            <!-- ###END###{FileSaver} -->
            <!-- ###BEGIN###{NetworkSettings} -->
            <div id="dialog20" style="margin:auto;margin:3px">
                <input type="radio" name="d20" id="d20a" value="0">désactivé<br>
                <input type="radio" name="d20" id="d20b" value="1">Réponse ICMP<br>
                <input type="radio" name="d20" id="d20c" value="2">Réponse RMCP<br>
                <input type="radio" name="d20" id="d20d" value="3">Réponse ICMP et RMCP<br><br>
            </div>
            <div id="dialog21" style="margin:auto;margin:3px">
                <div id="id_d21ipaddrsync">
                    <label><input type="checkbox" name="d21" id="d21ipsync" onclick="updateIPSetupDlg()">Synchronisation de l'adresse IP du système d'exploitation</label><br>
                </div>
                <label><input type="radio" name="d21" id="d21o0" onclick="updateIPSetupDlg()"><span id="d21l0"></span></label><br>
                <label><input type="radio" name="d21" id="d21o1" onclick="updateIPSetupDlg()"><span id="d21l1"></span></label><br>
                <div id="id_d21manualdiv">
                    <label><input type="radio" name="d21" id="d21o2" onclick="updateIPSetupDlg()"><span id="d21l2"></span></label><br><br>
                    <div style="margin-left:20px">
                        <div style="height:26px"><input id="idx_d21address" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>adresse IP</div></div>
                        <div style="height:26px" id="id_d21subnetdiv"><input id="idx_d21subnet" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>Marque de sous-réseau</div></div>
                        <div style="height:26px"><input id="idx_d21gateway" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>passerelle</div></div>
                        <div style="height:26px"><input id="idx_d21dns1" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>DNS principal</div></div>
                        <div style="height:26px"><input id="idx_d21dns2" onkeyup="updateIPSetupDlg()" style="float:right;width:230px"><div>DNS alternatif</div></div>
                    </div>
                </div>
            </div>
            <div id="dialog23" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="idx_d23ddns" style="float:right;width:200px" onchange="showEditDnsDlgChange()">
                        <option value="0">désactivé</option>
                        <option value="1">Désactivé, mise à jour DHCP</option>
                        <option value="2">Activée</option>
                    </select>
                    <div>Client DNS dynamique</div>
                </div>
                <div style="height:26px"><input id="idx_d23interval" style="float:right;width:200px"><div>Intervalle de mise à jour (minutes)</div></div>
                <div style="height:26px"><input id="idx_d23ttl" style="float:right;width:200px"><div>TTL (secondes)</div></div>
                <div style="font-size:10px"><br>L'intervalle par défaut est de 1440 minutes, le TTL par défaut est de 900 secondes.</div>
            </div>
            <!-- ###END###{NetworkSettings} -->
            <!-- ###BEGIN###{PowerControl-Advanced} -->
            <div id="dialog24" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="idx_d24Command" style="float:right;width:200px" onchange="showAdvPowerDlgChange()">
                        <option value="2">Power up</option>
                        <option value="10">Réinitialiser</option>
                        <option value="5">Cycle de puissance</option>
                        <option value="8">Éteindre</option>
                        <option id="d24p500" value="500">Réveil du système d'exploitation en veille</option>
                        <option id="d24p501" value="501">Économie d'énergie du système d'exploitation</option>
                        <option value="999">Définir les options de démarrage</option>
                    </select>
                    <div>Commande à distance</div>
                </div>
                <div style="height:80px">
                    <div id="idx_d24bootoptions" style="float:right;border:1px solid #666;width:200px;height:72px;overflow-y:scroll;background-color:white">
                        <div id="d24dBiosPause"><label><input type="checkbox" id="d24BiosPause" onchange="showAdvPowerDlgChange()">Pause du BIOS</label><br></div>
                        <div id="d24dBiosSecureBoot"><label><input type="checkbox" id="d24BiosSecureBoot" onchange="showAdvPowerDlgChange()">Appliquer le démarrage sécurisé</label><br></div>
                        <div id="d24dBiosSetup"><label><input type="checkbox" id="d24BiosSetup" onchange="showAdvPowerDlgChange()">Configuration du BIOS</label><br></div>
                        <div id="d24dForceProgressEvents"><label><input type="checkbox" id="d24ForceProgressEvents" onchange="showAdvPowerDlgChange()">Forcer les événements de progression</label><br></div>
                        <div id="d24dLockPowerButton"><label><input type="checkbox" id="d24LockPowerButton" onchange="showAdvPowerDlgChange()">Verrouiller le bouton d'alimentation</label><br></div>
                        <div id="d24dLockResetButton"><label><input type="checkbox" id="d24LockResetButton" onchange="showAdvPowerDlgChange()">Verrouiller le bouton de réinitialisation</label><br></div>
                        <div id="d24dLockSleepButton"><label><input type="checkbox" id="d24LockSleepButton" onchange="showAdvPowerDlgChange()">Verrouiller le bouton de veille</label><br></div>
                        <div id="d24dLockKeyboard"><label><input type="checkbox" id="d24LockKeyboard" onchange="showAdvPowerDlgChange()">Verrouiller le clavier</label><br></div>
                        <div id="d24dUserPasswordBypass"><label><input type="checkbox" id="d24UserPasswordBypass" onchange="showAdvPowerDlgChange()">Contournement du mot de passe du BIOS</label><br></div>
                        <div id="d24dReflashBios"><label><input type="checkbox" id="d24ReflashBios" onchange="showAdvPowerDlgChange()">Reflasher le BIOS</label><br></div>
                        <div id="d24dSafeMode"><label><input type="checkbox" id="d24SafeMode" onchange="showAdvPowerDlgChange()">Mode sans échec</label><br></div>
                        <div id="d24dUseIDER"><label><input type="checkbox" id="d24UseIDER" onchange="showAdvPowerDlgChange()">Utiliser IDER</label><br></div>
                        <div id="d24dSerialOverLan"><label><input type="checkbox" id="d24SerialOverLan" onchange="showAdvPowerDlgChange()">Série sur LAN</label><br></div>
                        <div id="d24dSecureErase"><label><input type="checkbox" id="d24SecureErase" onchange="showAdvPowerDlgChange()">Effacement sécurisé à distance Intel®</label><br></div>
                        <div id="d24dPlatformErase"><label><input type="checkbox" id="d24PlatformErase" onchange="showAdvPowerDlgChange()">Remote Platform Erase</label><br></div>
                        <div id="d24dFirmwareReset"><label><input type="checkbox" id="d24FirmwareReset" onchange="showAdvPowerDlgChange()">Clear Intel® ME Settings</label><br></div>
                    </div>
                    <div>Paramètres de démarrage</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d24ForceBootDevice" style="float:right;width:200px" onchange="showAdvPowerDlgChange()"></select>
                    <div>Source de démarrage</div>
                </div>
                <div id="idx_d24bootSource" style="height:26px">
                    <select id="idx_d24BootMediaIndex" style="float:right;width:200px" onchange="showAdvPowerDlgChange()">
                        <option value="0">Aucun</option>
                        <option value="1">Index 1</option>
                        <option value="2">Index 2</option>
                        <option value="3">Index 3</option>
                        <option value="3">Index 4</option>
                    </select>
                    <div>Boot Media</div>
                </div>
                <!-- ###BEGIN###{PowerControl-OneClick} -->
                <div id="idx_d24customBootSource" style="height:26px;display:none">
                    <select id="idx_d24customBootMediaIndex" onchange="showAdvPowerDlgChange()" style="float:right;width:200px"></select>
                    <div>Boot Media</div>
                </div>
                <div id="idx_d24diskImage" style="height:26px">
                    <input id="idx_d24ocrBootFile" type="file" onchange="showAdvPowerDlgChange()" style="float:right;width:200px" accept=".iso">                    
                    <div>Boot Image</div>
                </div>
                <div id="idx_d24diskImageUrl" style="height:26px">
                    <input id="idx_d24ocrBootUrl" type="text" onchange="showAdvPowerDlgChange()" onkeyup="showAdvPowerDlgChange()" placeholder="https://" style="float:right;width:200px">
                    <div>Boot URL</div>
                </div>
                <div id="idx_d24diskImageHttpTimeout" style="height:26px">
                    <input id="idx_d24ocrBootHttpBootTimeout" type="text" onchange="showAdvPowerDlgChange()" onkeyup="showAdvPowerDlgChange()" value="0" style="float:right;width:200px">
                    <div>Timeout (Seconds)</div>
                </div>
                <!-- ###END###{PowerControl-OneClick} -->
                <div style="height:26px" id="idd_d24IDERBootDevice">
                    <select id="idx_d24IDERBootDevice" style="float:right;width:200px" onchange="showAdvPowerDlgChange()">
                        <option value="0">Boot to floppy</option>
                        <option value="1">Démarrage sur CD-ROM</option>
                    </select>
                    <div>Périphérique de démarrage IDER</div>
                </div>
                <div style="height:26px">
                    <select id="idx_d24Verbocity" style="float:right;width:200px" onchange="showAdvPowerDlgChange()">
                        <option value="0">Défaut du système</option>
                        <option id="idx_d24Verbocity1" value="1">Silencieux</option>
                        <option id="idx_d24Verbocity2" value="2">Verbeux</option>
                        <option id="idx_d24Verbocity3" value="3">Écran blanc</option>
                    </select>
                    <div>Verbocity</div>
                </div>
                <div style="height:26px" id="idd_d24RSEPass">
                    <div style="float:right;width:200px"><input type="password" id="d24rsepass" maxlength="32" style="float:right;width:100%"></div>
                    <div>Mot de passe RSE</div>
                </div>
                <!-- ###BEGIN###{Mode-NodeWebkit} -->
                <div id="idd_d24RSEPassTlsWarn"><div style="color:red"><b>ATTENTION:</b> TLS n'est pas utilisé, le mot de passe sera envoyé en clair.</div></div>
                <!-- ###END###{Mode-NodeWebkit} -->
            </div>
            <!-- ###END###{PowerControl-Advanced} -->
            <!-- ###BEGIN###{Alarms} -->
            <div id="dialog25" style="margin:auto;margin:3px">
                <div style="text-align:left">
                    <div style="height:26px;margin-top:4px"><input id="d25alarm_name" style="float:right;width:180px" maxlength="32" onkeyup="alertDialogUpdate()"><div style="padding-top:4px">Nom de l'alarme</div></div>
                    <div style="height:26px;margin-top:4px">
                        <div style="float:right">
                            <input id="d25alarm_sdate" style="width:180px" maxlength="10" onkeyup="alertDialogUpdate()" onkeypress="return numbersOnly(event,45)">
                        </div>
                        <div style="padding-top:4px">Date de réveil (année-mois-jour)</div>
                    </div>
                    <div style="height:26px;margin-top:4px">
                        <div style="float:right">
                            <input id="d25alarm_stime" style="width:180px" maxlength="10" onkeyup="alertDialogUpdate()" onkeypress="return numbersOnly(event,58)">
                        </div>
                        <div style="padding-top:4px">Heure de réveil (heure: min: sec)</div>
                    </div>
                    <div style="height:26px;margin-top:4px">
                        <div style="float:right">
                            <input id="d25alarm_interval" style="width:180px" maxlength="10" onkeyup="alertDialogUpdate()" onkeypress="return numbersOnly(event,45)">
                        </div>
                        <div style="padding-top:4px">Intervalle (jours-heures-min)</div>
                    </div>
                    <div style="height:26px;margin-top:4px">
                        <div style="float:right;width:180px">
                            <select id="d25alarm_doc" style="width:100%" onchange="showAdvPowerDlgChange()">
                                <option value="0">Gardez l'alarme</option>
                                <option value="1">Supprimer à la fin</option>
                            </select>
                        </div>
                        <div style="padding-top:4px">Après le réveil</div>
                    </div>
                </div>
            </div>
            <!-- ###END###{Alarms} -->
            <div id="dialog26" style="margin:auto;margin:3px">
                <div id="d26rpediv">
                    <div>Remote Platform Erase (RPE)</div>
                    <label><input type="radio" name="d26b" id="idx_d26rpe1" value="2">Activée<br></label>
                    <label><input type="radio" name="d26b" id="idx_d26rpe0" value="0">désactivé<br></label>
                    <hr>
                </div>
                <div>One One Click Recovery (OCR)</div>
                <label><input type="radio" name="d26a" id="idx_d26ocr1" value="1">Activée<br></label>
                <label><input type="radio" name="d26a" id="idx_d26ocr0" value="0">désactivé<br></label>
            </div>
            <!-- ###BEGIN###{NetAuth} -->
            <div id="dialog27" style="margin:auto;margin:3px">
                <br>
                <div style="height:26px">
                    <select id="idx_d27enabled" style="float:right;width:200px" onclick="updateNetAuthDialog()">
                        <option value="0">désactivé</option>
                        <option value="1">Activée</option>
                    </select>
                    <div>Activée</div>
                </div>
                <div id="idx_d27protocoldiv" style="height:26px">
                    <select id="idx_d27protocol" style="float:right;width:200px" onclick="updateNetAuthDialog()">
                        <option value="0" selected="selected">EAP-TLS</option>
                        <option value="1">EAP-TTLS/MSCHAPv2</option>
                        <option value="2">PEAPv0/EAP-MSCHAPv2</option>
                        <option value="3">PEAPv1/EAP-GTC</option>
                        <option value="4">EAP-FAST/MSCHAPv2</option>
                        <option value="5">EAP-FAST/GTC</option>
                        <option value="6">EAP-FAST/TLS</option>
                    </select>
                    <div>Protocole</div>
                </div>
                <div id="idx_d27servernamediv" style="height:26px"><input id="idx_d27servername" style="float:right;width:200px" maxlength="80" onkeyup="updateNetAuthDialog()" title="32 caractères maximum"><div title="32 caractères maximum">Server Name</div></div>
                <div id="idx_d27servernamecomparediv" style="height:26px">
                    <select id="idx_d27servernamecompare" style="float:right;width:200px" onclick="updateNetAuthDialog()">
                        <option value="0" selected="selected">Full Name</option>
                        <option value="1">Domain Suffix</option>
                    </select>
                    <div>Server Name Compare</div>
                </div>
                <div id="idx_d27domaindiv" style="height:26px"><input id="idx_d27domain" style="float:right;width:200px" maxlength="128" onkeyup="updateNetAuthDialog()" title="Maximum 128 characters"><div title="Maximum 128 characters">Domain</div></div>
                <div id="idx_d27usernamediv" style="height:26px"><input id="idx_d27username" style="float:right;width:200px" maxlength="128" onkeyup="updateNetAuthDialog()" title="Maximum 128 characters"><div title="Maximum 128 characters">Nom d'utilisateur</div></div>
                <div id="idx_d27passworddiv" style="height:26px"><input id="idx_d27password" type="password" style="float:right;width:200px" maxlength="32" onkeyup="updateNetAuthDialog()" title="Maximum length is 32 characters"><div title="Maximum length is 32 characters">Mot de passe</div></div>
                <div id="idx_d27roamingidentitydiv" style="height:26px"><input id="idx_d27roamingidentity" style="float:right;width:200px" maxlength="80" onkeyup="updateNetAuthDialog()" title="Maximum 80 characters"><div title="Maximum 80 characters">Roaming Identity</div></div>
                <div id="idx_d27pacdiv" style="height:26px"><input id="idx_d27pac" style="float:right;width:200px" maxlength="256" onkeyup="updateNetAuthDialog()" title="Maximum 256 characters"><div title="Maximum 256 characters">Protected Access Credentials</div></div>
                <div id="idx_d27pacpassworddiv" style="height:26px"><input id="idx_d27pacpassword" type="password" style="float:right;width:200px" maxlength="256" onkeyup="updateNetAuthDialog()" title="Maximum length is 256 characters"><div title="Maximum length is 256 characters">PAC Password</div></div>
                <div id="idx_d27clientcertdiv" style="height:26px">
                    <select id="idx_d27clientcert" style="float:right;width:200px" onclick="updateNetAuthDialog()"></select>
                    <div>Client Certificate</div>
                </div>
                <div id="idx_d27servercertdiv" style="height:26px">
                    <select id="idx_d27servercert" style="float:right;width:200px" onclick="updateNetAuthDialog()"></select>
                    <div>Server Issuer Cert</div>
                </div>
                <div id="idx_d27activeins0div" style="height:26px">
                    <select id="idx_d27activeins0" style="float:right;width:200px" onclick="updateNetAuthDialog()">
                        <option value="0">Activée</option>
                        <option value="1">désactivé</option>
                    </select>
                    <div>Active in S0</div>
                </div>
                <div id="idx_d27pxetimeoutdiv" style="height:26px"><input id="idx_d27pxetimeout" style="float:right;width:200px" onkeyup="updateNetAuthDialog()"><div>PXE Timeout</div></div>
            </div>
            <!-- ###END###{NetAuth} -->
        </div>
        <div style="padding:10px;margin-bottom:4px">
            <input id="idx_dlgCancelButton" type="button" value="Annuler" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">
            <input id="idx_dlgOkButton" type="button" value="D'accord" style="float:right;width:80px" onclick="dialogclose(1)">
            <div style="height:25px"><input id="idx_dlgDeleteButton" type="button" value="Supprimer" style="width:80px;display:none" onclick="dialogclose(2)"></div>
        </div>
    </div>
    <!-- ###BEGIN###{ContextMenus} -->
    <div id="contextMenu" class="contextMenu" style="display:none"></div>
    <!-- ###END###{ContextMenus} -->
    <!-- ###BEGIN###{Mode-NodeWebkit} -->
    <!-- ###END###{Mode-NodeWebkit} -->
    <!-- ###BEGIN###{PowerControl} -->
    <!-- ###END###{PowerControl} -->
        <script type="text/javascript">
        // ###BEGIN###{!Look-BrandedCommander}
        var version = '0.9.6';
        // ###END###{!Look-BrandedCommander}
        // ###BEGIN###{Look-BrandedCommander}
        var version = '1.2.0';
        // ###END###{Look-BrandedCommander}
        var urlvars = {};
        var amtstack;
        var wsstack = null;
// ###BEGIN###{WsmanBrowser}
        var AllWsman = 'AMT_8021xCredentialContext,AMT_8021XProfile,AMT_ActiveFilterStatistics,AMT_AgentPresenceCapabilities,AMT_AgentPresenceInterfacePolicy,AMT_AgentPresenceService,AMT_AgentPresenceWatchdog,AMT_AgentPresenceWatchdogAction,AMT_AlarmClockService,IPS_AlarmClockOccurrence,AMT_AssetTable,AMT_AssetTableService,AMT_AuditLog,AMT_AuditPolicyRule,AMT_AuthorizationService,AMT_BootCapabilities,AMT_BootSettingData,AMT_ComplexFilterEntryBase,AMT_CRL,AMT_CryptographicCapabilities,AMT_EACCredentialContext,AMT_EndpointAccessControlService,AMT_EnvironmentDetectionInterfacePolicy,AMT_EnvironmentDetectionSettingData,AMT_EthernetPortSettings,AMT_EventLogEntry,AMT_EventManagerService,AMT_EventSubscriber,AMT_FilterEntryBase,AMT_FilterInSystemDefensePolicy,AMT_GeneralSettings,AMT_GeneralSystemDefenseCapabilities,AMT_Hdr8021Filter,AMT_HeuristicPacketFilterInterfacePolicy,AMT_HeuristicPacketFilterSettings,AMT_HeuristicPacketFilterStatistics,AMT_InterfacePolicy,AMT_IPHeadersFilter,AMT_KerberosSettingData,AMT_ManagementPresenceRemoteSAP,AMT_MessageLog,AMT_MPSUsernamePassword,AMT_NetworkFilter,AMT_NetworkPortDefaultSystemDefensePolicy,AMT_NetworkPortSystemDefenseCapabilities,AMT_NetworkPortSystemDefensePolicy,AMT_PCIDevice,AMT_PETCapabilities,AMT_PETFilterForTarget,AMT_PETFilterSetting,AMT_ProvisioningCertificateHash,AMT_PublicKeyCertificate,AMT_PublicKeyManagementCapabilities,AMT_PublicKeyManagementService,AMT_PublicPrivateKeyPair,AMT_RedirectionService,AMT_RemoteAccessCapabilities,AMT_RemoteAccessCredentialContext,AMT_RemoteAccessPolicyAppliesToMPS,AMT_RemoteAccessPolicyRule,AMT_RemoteAccessService,AMT_SetupAndConfigurationService,AMT_SNMPEventSubscriber,AMT_StateTransitionCondition,AMT_SystemDefensePolicy,AMT_SystemDefensePolicyInService,AMT_SystemDefenseService,AMT_SystemPowerScheme,AMT_ThirdPartyDataStorageAdministrationService,AMT_ThirdPartyDataStorageService,AMT_TimeSynchronizationService,AMT_TLSCredentialContext,AMT_TLSProtocolEndpoint,AMT_TLSProtocolEndpointCollection,AMT_TLSSettingData,AMT_TrapTargetForService,AMT_UserInitiatedConnectionService,AMT_WebUIService,AMT_WiFiPortConfigurationService,CIM_AbstractIndicationSubscription,CIM_Account,CIM_AccountManagementCapabilities,CIM_AccountManagementService,CIM_AccountOnSystem,CIM_AdminDomain,CIM_AlertIndication,CIM_AssignedIdentity,CIM_AssociatedPowerManagementService,CIM_AuthenticationService,CIM_AuthorizationService,CIM_Battery,CIM_BIOSElement,CIM_BIOSFeature,CIM_BIOSFeatureBIOSElements,CIM_BootConfigSetting,CIM_BootService,CIM_BootSettingData,CIM_BootSourceSetting,CIM_Capabilities,CIM_Card,CIM_Chassis,CIM_Chip,CIM_Collection,CIM_Component,CIM_ComputerSystem,CIM_ComputerSystemPackage,CIM_ConcreteComponent,CIM_ConcreteDependency,CIM_Controller,CIM_CoolingDevice,CIM_Credential,CIM_CredentialContext,CIM_CredentialManagementService,CIM_Dependency,CIM_DeviceSAPImplementation,CIM_ElementCapabilities,CIM_ElementConformsToProfile,CIM_ElementLocation,CIM_ElementSettingData,CIM_ElementSoftwareIdentity,CIM_ElementStatisticalData,CIM_EnabledLogicalElement,CIM_EnabledLogicalElementCapabilities,CIM_EthernetPort,CIM_Fan,CIM_FilterCollection,CIM_FilterCollectionSubscription,CIM_HostedAccessPoint,CIM_HostedDependency,CIM_HostedService,CIM_Identity,CIM_IEEE8021xCapabilities,CIM_IEEE8021xSettings,CIM_Indication,CIM_IndicationService,CIM_InstalledSoftwareIdentity,CIM_KVMRedirectionSAP,CIM_LANEndpoint,CIM_ListenerDestination,CIM_ListenerDestinationWSManagement,CIM_Location,CIM_Log,CIM_LogEntry,CIM_LogicalDevice,CIM_LogicalElement,CIM_LogicalPort,CIM_LogicalPortCapabilities,CIM_LogManagesRecord,CIM_ManagedCredential,CIM_ManagedElement,CIM_ManagedSystemElement,CIM_MediaAccessDevice,CIM_MemberOfCollection,CIM_Memory,CIM_MessageLog,CIM_NetworkPort,CIM_NetworkPortCapabilities,CIM_NetworkPortConfigurationService,CIM_OrderedComponent,CIM_OwningCollectionElement,CIM_OwningJobElement,CIM_PCIController,CIM_PhysicalComponent,CIM_PhysicalElement,CIM_PhysicalElementLocation,CIM_PhysicalFrame,CIM_PhysicalMemory,CIM_PhysicalPackage,CIM_Policy,CIM_PolicyAction,CIM_PolicyCondition,CIM_PolicyInSystem,CIM_PolicyRule,CIM_PolicyRuleInSystem,CIM_PolicySet,CIM_PolicySetAppliesToElement,CIM_PolicySetInSystem,CIM_PowerManagementCapabilities,CIM_PowerManagementService,CIM_PowerSupply,CIM_Privilege,CIM_PrivilegeManagementCapabilities,CIM_PrivilegeManagementService,CIM_ProcessIndication,CIM_Processor,CIM_ProtocolEndpoint,CIM_ProvidesServiceToElement,CIM_Realizes,CIM_RecordForLog,CIM_RecordLog,CIM_RedirectionService,CIM_ReferencedProfile,CIM_RegisteredProfile,CIM_RemoteAccessAvailableToElement,CIM_RemoteIdentity,CIM_RemotePort,CIM_RemoteServiceAccessPoint,CIM_Role,CIM_RoleBasedAuthorizationService,CIM_RoleBasedManagementCapabilities,CIM_RoleLimitedToTarget,CIM_SAPAvailableForElement,CIM_SecurityService,CIM_Sensor,CIM_Service,CIM_ServiceAccessBySAP,CIM_ServiceAccessPoint,CIM_ServiceAffectsElement,CIM_ServiceAvailableToElement,CIM_ServiceSAPDependency,CIM_ServiceServiceDependency,CIM_SettingData,CIM_SharedCredential,CIM_SoftwareElement,CIM_SoftwareFeature,CIM_SoftwareFeatureSoftwareElements,CIM_SoftwareIdentity,CIM_StatisticalData,CIM_StorageExtent,CIM_System,CIM_SystemBIOS,CIM_SystemComponent,CIM_SystemDevice,CIM_SystemPackaging,CIM_UseOfLog,CIM_Watchdog,CIM_WiFiEndpoint,CIM_WiFiEndpointCapabilities,CIM_WiFiEndpointSettings,CIM_WiFiPort,CIM_WiFiPortCapabilities,IPS_AdminProvisioningRecord,IPS_ClientProvisioningRecord,IPS_HostBasedSetupService,IPS_HostIPSettings,IPS_HTTPProxyService,IPS_HTTPProxyAccessPoint,IPS_IderSessionUsingPort,IPS_IPv6PortSettings,IPS_KVMRedirectionSettingData,IPS_KvmSessionUsingPort,IPS_ManualProvisioningRecord,IPS_OptInService,IPS_PowerManagementService,IPS_ProvisioningAuditRecord,IPS_ProvisioningRecordLog,IPS_RasSessionUsingPort,IPS_ScreenConfigurationService,IPS_ScreenSettingData,IPS_SecIOService,IPS_SessionUsingPort,IPS_SolSessionUsingPort,IPS_TLSProvisioningRecord,IPS_WatchDogAction'.split(',');
// ###END###{WsmanBrowser}
        var disconnecturl = null;
// ###BEGIN###{Terminal}
        var terminal;
// ###END###{Terminal}
        var currentView = 0;
        var LoadingHtml = '<div style=text-align:center;padding-top:20px>' + "Chargement..." + '<div>';
        var amtversion = 0;
        var amtversionmin = 0;
        var amtFirstPull = 0; // Bitmask, Set this when the first pull request is made on a device: 1 = HardwareInfo, 2 = WirelessInfo, 4 = SystemDefense, 8 = Storage, 16 = EventLog, 32 = AuditLog, 64 = ExtraInfo, 128 = 802.1x
// ###BEGIN###{NetworkSettings}
        var amtwirelessif = -1; // Set to the interface index for the wireless interface, -1 if no wireless.
// ###END###{NetworkSettings}
// ###BEGIN###{Desktop}
        var desktop;
        var desktopsettings = { encflags: 1, showfocus: false, showmouse: true, showcad: true, limitFrameRate: false, noMouseRotate: false, decimationMode: 2 };
// ###END###{Desktop}
// ###BEGIN###{Mode-MeshCentral2}
        var currentMeshNode = null;
// ###END###{Mode-MeshCentral2}
        var webcompilerfeatures = [/*###WEBCOMPILERFEATURES###*/];
        var StatusStrs = ["Débranché", "De liaison...", "Installer...", "Lié"];
// ###BEGIN###{Scripting}
        var scriptstate;
// ###END###{Scripting}
// ###BEGIN###{USBSetup}
        var setupbin;
        var selectedRecord = 0;
        var selectedVariable = 0;
// ###END###{USBSetup}
// ###BEGIN###{!Mode-MeshCentral2}
        var amtPowerPollTimer = null;
// ###END###{!Mode-MeshCentral2}
// ###BEGIN###{Mode-LMS}
        var lms = null;
        // ###END###{Mode-LMS}
        // ###BEGIN###{ComputerSelector-Local}
            // ###BEGIN###{Mode-NodeWebkit}
            var kerberos;
            try { kerberos = require('krb-ticket'); } catch (e) { console.log("Impossible de configurer les kerberos"); }
            if (!kerberos || kerberos.initialize() != 0) { kerberos = null; }
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            var kerberos = null;
            // ###END###{!Mode-NodeWebkit}
            var filterFocus = false;
        // ###END###{ComputerSelector-Local}
        var t, t2, rsepass = null; // Global temporary variable
        // ###BEGIN###{MeshServerConnect}
        var meshCentralServer = null;
        // ###END###{MeshServerConnect}
        // ###BEGIN###{PowerControl-Advanced}
        // ###BEGIN###{PowerControl-OneClick}
        var webserver = null;
        // ###END###{PowerControl-OneClick}
        // ###END###{PowerControl-Advanced}
        // ###BEGIN###{DesktopClipboard}
        var xxKvmClipEnc = null;
        var xxKvmClipVal = null;
        // ###END###{DesktopClipboard}

        function startup() {
            // This is a bit freeky, but all HTML input elements are just going to be accessible directly.
            var allelements = document.getElementsByTagName('input');
            for (t = 0; t < allelements.length; t++) { if (allelements[t].id) { window[allelements[t].id] = allelements[t]; } }

            // ###BEGIN###{!Mode-NodeWebkit}
            urlvars = getUrlVars();
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}

            // Move things around to make space for the left-side toolbar
            QS('id_computerSelector').left = '52px';
            QS('id_computerListParent').left = '52px';
            QS('id_certManagerPanel').left = '52px';
            QS('id_certManagerPanel2').left = '52px';
            QS('id_usbSetupPanel').left = '52px';
            QS('id_usbSetupPanel2').left = '52px';
            // ###BEGIN###{SessionRecording}
            QS('id_sessionPlayerPanel').left = '52px';
            // ###END###{SessionRecording}

            // Parse the runtime arguments
            urlvars = getUrlVars();
            var argv = require('nw.gui').App.argv;
            for (var i in argv) {
                if (argv[i].substring(0,1) == '-') {
                    var j = argv[i].indexOf(':');
                    if (j == -1) {
                        urlvars[argv[i].substring(1)] = 1;
                    } else {
                        urlvars[argv[i].substring(1, j)] = argv[i].substring(j + 1);
                    }
                }
            }

            // If we are in NodeWebkit, check if we need to start a output log.
            if (urlvars.logfile && (typeof urlvars.logfile == 'string')) {
                g_logFile = require('fs').createWriteStream(urlvars.logfile, { flags: 'a' }); // Or 'w' to truncate the file every time the process starts.
                g_logStdout = process.stdout;
                console.logEx = console.log;
                console.log = function () {
                    if (arguments.length == 1) console.logEx(arguments[0]);
                    if (arguments.length == 2) console.logEx(arguments[0], arguments[1]);
                    if (arguments.length == 3) console.logEx(arguments[0], arguments[1], arguments[2]);
                    if (arguments.length == 4) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3]);
                    if (arguments.length == 5) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
                    if (arguments.length == 6) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
                    if (arguments.length == 7) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
                    if (arguments.length == 8) console.logEx(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]);
                    g_logFile.write(require('util').format.apply(null, arguments) + '\r\n');
                    //g_logStdout.write(require('util').format.apply(null, arguments) + '\r\n'); //console.errorEx(arguments);
                }
                console.errorEx = console.error;
                console.error = console.log;
                console.log('--- LOG START: ' + new Date() + ' ---');
            }

            // If we are in NodeWebkit, check if we need to display the console window
            if (urlvars['debug'] == 1) { require('nw.gui').Window.get().showDevTools(); }

            // Prepend 'script' and 'list' with working directory if set and ':' is not in the string. This covers the case where self-extracting Commander has working directory set incorrectly.
            if (urlvars['script'] && (urlvars['script'].indexOf(':') < 0)) { urlvars['script'] = require('path').dirname(process.execPath) + '\\' + urlvars['script']; }
            if (urlvars['list'] && (urlvars['list'].indexOf(':') < 0)) { urlvars['list'] = require('path').dirname(process.execPath) + '\\' + urlvars['list']; }

            // Setup the TLS security mode
            try {
                NW_TlsSecurityMode = parseInt(localStorage.getItem('TlsSecurityMode') ? localStorage.getItem('TlsSecurityMode') : '1');
                NW_SkipTlsHostnameCheck = parseInt(localStorage.getItem('SkipTlsHostnameCheck') ? localStorage.getItem('SkipTlsHostnameCheck') : '0');
            } catch (ex) {
                NW_TlsSecurityMode = '1';
                NW_SkipTlsHostnameCheck = '0';
            }
            if (urlvars['tlssecurity']) { NW_TlsSecurityMode = parseInt(urlvars['tlssecurity']); }
            if (urlvars['ignoretls']) { NW_TlsSecurityMode = 0; }
            if (urlvars['skiptlshostcheck']) { NW_SkipTlsHostnameCheck = parseInt(urlvars['skiptlshostcheck']); }
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{DesktopClipboard}
            if (urlvars['kvmclip']) { QV('id_DeskKvmClipButton', true); }
            // ###END###{DesktopClipboard}

            // ###BEGIN###{ContextMenus}
            document.onclick = function (e) { hideContextMenu(); }
            // ###END###{ContextMenus}

            // ###BEGIN###{SessionRecording}
            srec_cleanup();
            Q('srec_PlaySpeed').value = 1;
            // ###END###{SessionRecording}

            // ###BEGIN###{Mode-LMS}
            // Setup LMS
            lms = CreateLmsControl();
            lms.onStateChanged = lmsChangedState;
            lms.onData = lmsOnData;
            lms.Start();
            QH('id_lmsData', LoadingHtml);
            QH('id_lmsData', '');
            QH('id_computername', 'Configuration Console v' + version);
            go(101);
            lmsRefresh();
            // ###END###{Mode-LMS}

            // ###BEGIN###{WsmanBrowser}
            // Add all WSMAN objects to WSMAN browser
            for (var w in AllWsman) { var option = document.createElement('option'); option.text = AllWsman[w]; option.id = 'WSB-' + AllWsman[w]; Q('id_QuerySelect').add(option); }
            // ###END###{WsmanBrowser}

            // ###BEGIN###{Desktop}
            // Setup the remote desktop
            desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk', Q('id_mainarea')));
            desktop.onStateChanged = onDesktopStateChange;
            QE('idx_connectbutton1', true);
            try { t = localStorage.getItem('desktopsettings'); } catch (ex) {}
            if (t) { desktopsettings = JSON.parse(t); }
            if (urlvars.kvmenc) { var v = parseInt(urlvars.kvmenc); if (typeof v == 'number') { desktopsettings.encflags = v; } }
            if (urlvars.kvmdec) { var v = parseInt(urlvars.kvmdec); if (typeof v == 'number') { desktopsettings.decimationMode = v; } }
            applyDesktopSettings();
            var s = '';
            //for (var c = 1; c < 13; c++) s += '<option value="' + (0xffbd + c) + '">F' + c +;
            //QH('specialkeylist', s);
            // ###END###{Desktop}

            // ###BEGIN###{Terminal}
            // Setup the terminal
            terminal = CreateAmtRedirect(CreateAmtRemoteTerminal('Term'));
            terminal.onStateChanged = onTerminalStateChange;
            // ###BEGIN###{Terminal-Enumation-All}
            Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
            // ###END###{Terminal-Enumation-All}
            Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n')?"CR + LF":"LF";

            QE('idx_connectbutton2', true);

            // Setup Terminal drag & drop
            Q('p13').addEventListener('dragover', haltEvent, false);
            Q('p13').addEventListener('dragleave', haltEvent, false);
            Q('p13').addEventListener('drop', terminal_FileSelectHandler, false);
            // ###END###{Terminal}

            // Main drag & drop
            document.addEventListener('dragover', haltEvent, false);
            document.addEventListener('dragleave', haltEvent, false);
            document.addEventListener('drop', documentFileSelectHandler, false);

            // ###BEGIN###{Certificates}
            // Setup Terminal drag & drop
            Q('p16').addEventListener('dragover', haltEvent, false);
            Q('p16').addEventListener('dragleave', haltEvent, false);
            Q('p16').addEventListener('drop', cert_FileSelectHandler, false);
            // ###END###{Certificates}

            // ###BEGIN###{CertificateManager}
            // Setup Certificate Manager drag & drop
            Q('id_certManagerPanel').addEventListener('dragover', haltEvent, false);
            Q('id_certManagerPanel').addEventListener('dragleave', haltEvent, false);
            Q('id_certManagerPanel').addEventListener('drop', cert_importCertOk2, false);
            // ###END###{CertificateManager}

            // ###BEGIN###{CertificateManager}
            cert_loadCertificates();
            cert_updateCertificateList();
            // ###END###{CertificateManager}

            // ###BEGIN###{FileSaver}
            // ###BEGIN###{Desktop}
            // ###BEGIN###{!Mode-NodeWebkit}
            if (!Q('Desk')['toBlob']) { QV('idx_deskSaveBtn', false); }// On some browsers like IE, we can't save screen shots. Hide the sceeenshot/capture buttons.
            // ###END###{!Mode-NodeWebkit}
            // ###END###{Desktop}
            // ###END###{FileSaver}

            // ###BEGIN###{ComputerSelector}

            if (!urlvars['host']) { go(101); }
            QH('id_computername', format("Console de gestion à distance v{0}", version));

            // ###BEGIN###{ComputerSelector-Local}
            if (urlvars['host']) {
                // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                // If host is set to a hostname, connect directly to that computer
                var xuser = urlvars['user'];
                if (!xuser) xuser = '*'; // If user not set, default to * and use Kerberos
                var xpass = urlvars['pass'];
                if (!xpass) xpass = ''; // If password not set, default to blank.
                var xtls = 0;
                if (urlvars['tls'] == 1) { xtls = 1; }

                currentcomputer = { 'host': urlvars['host'], 'host': urlvars['host'], 'user': xuser, 'pass': xpass, 'tls': xtls, 'h': Math.random() };
                // ###BEGIN###{Mode-NodeWebkit}
                currentcomputer['tlscerthash'] = getCertPinning(urlvars['host']); // If we have a pinned TLS cert, add it here.
                // ###END###{Mode-NodeWebkit}
                disconnecturl = urlvars['disconnecturl'];
                if (!disconnecturl) disconnecturl = 'none';
                if (disconnecturl == 'none') QV('disconnectButton', false);
                if (disconnecturl == 'close') Q('disconnectButton').value = 'Close';
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                if ((currentcomputer['user'] == '*') || (currentcomputer['pass'] != '')) {
                    // Don't prompt the user for password, just connect. This is Kerberos or password already provided.
                    connect(ports.host, ports.http, currentcomputer['user'], currentcomputer['pass'], currentcomputer['tls']);
                } else {
                    // Prompt the user for digest password.
                    computerlist = [currentcomputer];
                    updateComputerList();
                    computerConnect(null, currentcomputer.h);
                }

                // ###END###{!ComputerSelector-Local-ScriptOnly}
                // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
                updateComputerList();
                // ###END###{ComputerSelector-Local-ScriptOnly}
            }
                // ###BEGIN###{!Mode-NodeWebkit}
            else if (urlvars['connect']) { loadServerComputer(); }
                // ###END###{!Mode-NodeWebkit}
            else {
                // ###BEGIN###{Mode-NodeWebkit}
                if (urlvars['list']) {
                    // Read the computers from a file list
                    var listok = 0;
                    try {
                        var ctext = require('fs').readFileSync(urlvars['list'], 'utf8');
                        if ((ctext.length > 2) && (ctext.charCodeAt(0) == 65533) && (ctext.charCodeAt(1) == 65533)) { // This is unicode detection
                            ctext = require('fs').readFileSync(urlvars['list'], 'utf16le');
                            if ((ctext.length > 1) && (ctext.charCodeAt(0) == 65279)) { ctext = ctext.substring(1); }
                        }
                        if (ctext) {
                            computerlist = JSON.parse(ctext);
                            if (computerlist.computers) { computerlist = computerlist.computers; }
                            var pins = getCertPinnings();
                            for (var i in computerlist) {
                                computerlist[i].checked = false;
                                if (!computerlist[i]['h']) computerlist[i]['h'] = Math.random(); // If 'h' handle is not present, create one.
                                if (!computerlist[i]['tls']) computerlist[i]['tls'] = 0; // If TLS is not present, assume 0.
                                if (!computerlist[i]['host'] && computerlist[i]['fqdn']) computerlist[i]['host'] = computerlist[i]['fqdn'];
                                if (!computerlist[i]['pass'] == null) computerlist[i]['pass'] = '';
                                if (computerlist[i]['fqdn']) delete computerlist[i]['fqdn'];

                                // Add stored certificate pinning.
                                if ((computerlist[i]['tlscerthash'] == null) && (pins[computerlist[i]['host']] != null)) { computerlist[i]['tlscerthash'] = pins[computerlist[i]['host']]; }
                                delete computerlist[i]['tlscert2'];
                                delete computerlist[i]['tlscerthash2'];
                            }
                            listok = computerlist.length;
                            if (listok > 0) updateComputerList();
                        }
                    } catch (e) { messagebox("Liste des ordinateurs", "Fichier de liste non valide: " + e) }
                    // Run a script on all computers
                    if (urlvars['script'] && listok > 0) {
                        // Select all computers
                        for (var i in computerlist) { Q('SJ-' + computerlist[i]['h']).checked = true; }
                        // Run the script
                        try {
                            var data = require('fs').readFileSync(urlvars['script'], 'utf8');
                            if (data) { mscript_onScriptRead( { target: { result: data }}, 1 ); }
                        } catch (e) { messagebox("Script de lancement", "Fichier de script non valide.") }
                    }
                } else {
                    // Setup the computer selector
                    loadComputers();
                }
                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{!Mode-NodeWebkit}
                // Setup the computer selector
                loadComputers();
                // ###END###{!Mode-NodeWebkit}
            }
            // ###END###{ComputerSelector-Local}

            // ###BEGIN###{ComputerSelector-Remote}
            // Load the list of computers from the server
            loadServerComputerList();
            // ###END###{ComputerSelector-Remote}

            // ###END###{ComputerSelector}

            // ###BEGIN###{Mode-Firmware}
            connect('/wsman');
            // ###END###{Mode-Firmware}

            // ###BEGIN###{USBSetup}
            usb_displaySetupBin();

            // Add all possible variable types to dialog 16
            var options = '';
            for (var i in AmtSetupBinVarIds) { for (var j in AmtSetupBinVarIds[i]) { options += '<option value="' + i + '-' + j + '">' + AmtSetupBinVarIds[i][j][1] } }
            QH('d16type', options);
            // ###END###{USBSetup}

            document.onkeyup = handleKeyUp;
            document.onkeydown = handleKeyDown;
            document.onkeypress = handleKeyPress;
            window.onresize = center;
            center();

            // ###BEGIN###{Mode-NodeWebkit}
            NW_WindowTitle = require('nw.gui').Window.get().title;
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{Scripting-Editor}
            // ###BEGIN###{!Mode-Firmware}
            scriptLoadStartingBlocks();
            // ###END###{!Mode-Firmware}
            // ###END###{Scripting-Editor}

            // ###BEGIN###{Mode-NodeWebkit}
            NW_AutoUpdateCheck();
            // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
            if (urlvars['help'] || urlvars['?']) { messagebox("Options de la ligne de commande", '<div style=text-align:left><b>-host:[hostname]</b>, ' + "Nom d'hôte ou IP d'Intel&reg; AMT" + '<br/><b>-user:[username]</b>, ' + "Identifiant de connexion au résumé" + '<br/><b>-pass:[password]</b>, ' + "Mot de passe de connexion Digest" + '<br/><b>-tls</b>, ' + "Connectez-vous à l'aide de la sécurité TLS" + '<br/><b>-kvm</b>, ' + "Une fois connecté, accédez au bureau à distance" + '<br/><b>-kvmfull</b>, ' + "Une fois connecté, accédez au bureau à distance en plein écran" + '<br/><b>-kvmonly</b>, ' + "Exécuter un bureau à distance en plein écran uniquement" + '<br/><b>-sol</b>, ' + "Une fois connecté, allez au terminal" + '<br/><b>-script:[file]</b>, ' + "Exécutez un script" + '<br/><b>-autoexit</b>, ' + "Quitter une fois le script terminé" + '<br/><b>-ignoretls</b>, ' + "Ne pas vérifier le certificat Intel&reg; AMT TLS" + '<br/></div>'); }
            // ###END###{!ComputerSelector-Local-ScriptOnly}
            // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
            if (urlvars['help'] || urlvars['?']) { messagebox("Options de la ligne de commande", '<div style=text-align:left><b>-list:[listfile]</b>, ' + "List of computers to run a script on" + '<br/><b>-script:[file]</b>, ' + "Exécutez un script" + '<br/><b>-autoexit</b>, ' + "Exit after all scripts are done" + '<br/><b>-ignoretls</b>, ' + "Ne pas vérifier le certificat Intel&reg; AMT TLS" + '<br/></div>'); }
            // ###END###{ComputerSelector-Local-ScriptOnly}
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{DesktopInbandFiles}
            // Setup upload drag & drop
            Q('p24filetable').addEventListener('drop', p24fileDragDrop, false);
            Q('p24filetable').addEventListener('dragover', p24fileDragOver, false);
            Q('p24filetable').addEventListener('dragleave', p24fileDragLeave, false);
            // ###END###{DesktopInbandFiles}

            // ###BEGIN###{DesktopRecorder}
            if (urlvars && urlvars['norecord']) { QV('id_DeskRecorderTools', false); }
            // ###END###{DesktopRecorder}

            // ###BEGIN###{Mode-NodeWebkit}
            // Check input arguments
            if (urlvars['webcn'] == 1) { delete urlvars['webcn']; setTimeout(function() { alert('Invalid webcn argument, use -webcn:domain.com.'); }, 100); }
            // ###END###{Mode-NodeWebkit}
        }

        // ###BEGIN###{PowerControl-Advanced}
        // ###BEGIN###{PowerControl-OneClick}
        function setupWebServer(leafCN) {
            if ((webserver != null) && (webserver.certCommonName == leafCN)) return;

            // Stop the web server if present
            if (webserver != null) { webserver.stop(); webserver = null; }

            // Create a web server to serve One Client Recovery (OCR) disk image files.
            webserver = CreateWebServer();
            webserver.generateCertificate(leafCN);
            webserver.start();
            webserver.onTransfers = function (webserver, transfers) {
                var x = '';
                for (var i in transfers) { x += '<div style="width:350px;position:relative;padding:3px"><span style="position:absolute;padding:3px;font-weight:bold">' + transfers[i].xfilename + '</span><div style="height:20px;background-color:#4CAF50;width:' + Math.floor((transfers[i].progress.count * 100) / transfers[i].xsize) + '%;border-radius:4px"></div></div>'; }
                QV('TransferNotification', transfers.length > 0);
                QH('TransferNotification', x);
            }

            //console.log('WebServer Cert Hash RAW', webserver.certHashRaw);
            //console.log('WebServer Cert Hash HEX', webserver.certHashHex);
        }
        // ###END###{PowerControl-OneClick}
        // ###END###{PowerControl-Advanced}

        function documentFileSelectHandler(e) {
            haltEvent(e);
            // ###BEGIN###{IDER}
            var diskimages = true;
            for (var i = 0; i < e.dataTransfer.files.length; i++) {
                if ((e.dataTransfer.files[i].name.toLowerCase().endsWith('.img') == false) && (e.dataTransfer.files[i].name.toLowerCase().endsWith('.iso') == false)) { diskimages = false; }
            }
            if ((diskimages == true) && (e.dataTransfer != null) && (currentView > 0) && (currentView < 100) && ((e.dataTransfer.files.length == 1) || (e.dataTransfer.files.length == 2))) {
                var floppyfile = null, cdromfile = null;
                if (e.dataTransfer.files[0].name.toLowerCase().endsWith('.iso')) { cdromfile = e.dataTransfer.files[0]; }
                if (e.dataTransfer.files[0].name.toLowerCase().endsWith('.img')) { floppyfile = e.dataTransfer.files[0]; }
                if (e.dataTransfer.files.length == 2) {
                    if (e.dataTransfer.files[1].name.toLowerCase().endsWith('.iso')) { cdromfile = e.dataTransfer.files[1]; }
                    if (e.dataTransfer.files[1].name.toLowerCase().endsWith('.img')) { floppyfile = e.dataTransfer.files[1]; }
                }
                if ((floppyfile != null) || (cdromfile != null)) iderStart3(floppyfile, cdromfile, 1);
                return;
            }
            // ###END###{IDER}

            if (e.dataTransfer == null || e.dataTransfer.files.length != 1) return;
            var f = null, filename = e.dataTransfer.files[0].name.toLowerCase();
            // ###BEGIN###{Storage}
            if (currentView == 21) { UploadToStorage(e.dataTransfer.files[0], filename); return; }
            // ###END###{Storage}
            // ###BEGIN###{ComputerSelector-Local}
            if (currentView == 101) {
                if (filename.endsWith('.mescript') || filename.endsWith('.meblocks')) { f = mscript_onScriptRead; }
                if (filename.endsWith('.json') || filename.endsWith('.csv')) { f = function (file) { onComputerListRead(file, filename); } }
            }
            // ###END###{ComputerSelector-Local}
            // ###BEGIN###{USBSetup}
            if (currentView == 102 && filename.endsWith('.bin')) { f = usb_onSetupBinRead; }
            // ###END###{USBSetup}
            // ###BEGIN###{Scripting}
            if (wsstack != null && (filename.endsWith('.mescript') || filename.endsWith('.meblocks'))) { f = script_onScriptRead; }
            // ###END###{Scripting}
            // ###BEGIN###{SessionRecording}
            if (currentView == 104 && filename.endsWith('.mcrec')) { srec_ondrop(e); return; }
            // ###END###{SessionRecording}
            if (f != null) { var reader = new FileReader(); reader.onload = f; reader.readAsBinaryString(e.dataTransfer.files[0]); }
        }

// ###BEGIN###{Mode-NodeWebkit}

        // ###BEGIN###{Look-Commander}
        function NW_CheckForUpdateMenu() {
            if (NW_UpdateMenuItem.checked == true) { NW_AutoUpdateCheck(); }
            try { localStorage.setItem('checkForUpdate', NW_UpdateMenuItem.checked); } catch (ex) { }
        }
        // ###END###{Look-Commander}

        // ###BEGIN###{Look-BrandedCommander}
        function NW_CheckForUpdateMenu() {
            if (NW_UpdateMenuItem.checked == true) { NW_AutoUpdateCheck(); }
            try { localStorage.setItem('checkForUpdate', NW_UpdateMenuItem.checked); } catch (ex) { }
        }
        // ###END###{Look-BrandedCommander}

        // Check if an update is available
        function NW_AutoUpdateCheck() {
            // ###BEGIN###{Look-Commander}
            // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
            try {
                if (localStorage.getItem('checkForUpdate') != 'false') {
                    var request = new XMLHttpRequest();
                    request.onload = function () {
                        if (request.status >= 200 && request.status < 400) {
                            var x = request.responseText, i = x.indexOf('##3B356F7A-0854-4EBA-B10D-4CC4FB522695##');
                            if (i > 0) {
                                x = x.substring(i);
                                var newversion = parseInt(x.substring(40, 46));
                                var criticalversion = parseInt(x.substring(48, 54));
                                var url = x.substring(56);
                                var j = url.indexOf('##');
                                if (j >= 0) {
                                    url = url.substring(0, j);
                                    var currentversion = version.split('.');
                                    currentversion = parseInt(currentversion[0] * 10000) + parseInt(currentversion[1] * 100) + parseInt(currentversion[2]);
                                    if (currentversion < newversion) {
                                        var newversiontext = Math.floor(newversion / 10000) + '.' + (Math.floor(newversion / 100) % 100) + '.' + (newversion % 100);
                                        var msg = format("MeshCommander v {0} est disponible", newversiontext);
                                        if (currentversion < criticalversion) {
                                            msg += ", c'est une mise à jour de sécurité critique";
                                            QS('UpdateNotification')['background-color'] = 'orange';
                                        }
                                        QH('UpdateNotificationText', msg);
                                        QV('UpdateNotification', true);
                                    }
                                }
                            }
                        }
                    };
                    request.onerror = function () { console.log('Failed to get script blocks'); };
                    request.open('GET', 'https://sites.google.com/site/opensoftwareprojects/mesh/security-1/autoupdate', true);
                    request.send();
                }
            } catch (ex) { }
            // ###END###{!ComputerSelector-Local-ScriptOnly}
            // ###END###{Look-Commander}
            // ###BEGIN###{Look-BrandedCommander}
            try {
                if (localStorage.getItem('checkForUpdate') != 'false') {
                    var request = new XMLHttpRequest();
                    request.onload = function () {
                        if (request.status >= 200 && request.status < 400) {
                            var x = request.responseText, i = x.indexOf('##371cff53-32b7-4278-86c5-3e6906965332##');
                            if (i > 0) {
                                x = x.substring(i);
                                var newversion = parseInt(x.substring(40, 46));
                                var criticalversion = parseInt(x.substring(48, 54));
                                var url = x.substring(56);
                                var j = url.indexOf('##');
                                if (j >= 0) {
                                    url = url.substring(0, j);
                                    var currentversion = version.split('.');
                                    currentversion = parseInt(currentversion[0] * 10000) + parseInt(currentversion[1] * 100) + parseInt(currentversion[2]);
                                    if (currentversion < newversion) {
                                        var newversiontext = Math.floor(newversion / 10000) + '.' + (Math.floor(newversion / 100) % 100) + '.' + (newversion % 100);
                                        var msg = format("Intel&reg; Manageability Commander v{0} is available", newversiontext);
                                        if (currentversion < criticalversion) {
                                            msg += ", c'est une mise à jour de sécurité critique";
                                            QS('UpdateNotification')['background-color'] = 'orange';
                                        }
                                        QH('UpdateNotificationText', msg);
                                        QV('UpdateNotification', true);
                                    }
                                }
                            }
                        }
                    };
                    request.onerror = function () { console.log('Failed to get script blocks'); };
                    request.open('GET', 'https://software.intel.com/en-us/articles/intel-manageability-commander', true);
                    request.send();
                }
            } catch (ex) { }
            // ###END###{Look-BrandedCommander}
        }

        function NW_HideUpdateNotification() {
            QV('UpdateNotification', false);
        }

        function NW_PerformUpdate() {
            require('nw.gui').Shell.openExternal('http://www.meshcommander.com/meshcommander');
        }

        var NW_WindowTitle = null;
        var NW_UpdateMenuItem = null;
        var NW_AmtScanMenuItem = null;
        var NW_TlsSecurityMode = 1;
        var NW_SkipTlsHostnameCheck = 0;

        function NW_SetupMainMenu(x) {
            var gui = require('nw.gui');
            var mainmenu = new gui.Menu({ type: 'menubar' });
            
            // Add Mac OS X specific menu
            var os = require('os');
            if (os.platform() == 'darwin') { mainmenu.createMacBuiltin('MeshCommander', { hideEdit: true, hideWindow: true }); }
            var filemenu = new gui.MenuItem({ label: "Fichier" });
            var filemenusub = new gui.Menu();
            var seperator = false;
            var toolsmenu = null;
            var scriptmenu = null;
            var securitymenu = null;
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer == null) {
            // ###END###{MeshServerConnect}
            if (x == 101) {
                // Computer selector
                filemenusub.append(new gui.MenuItem({ label: "Ajouter un ordinateur Intel AMT ...", click: addComputer }));
                filemenusub.append(new gui.MenuItem({ label: "Charger des ordinateurs ...", click: NW_LoadComputers }));
                filemenusub.append(new gui.MenuItem({ label: "Enregistrer les ordinateurs ...", click: NW_SaveComputers }));
                // ###BEGIN###{ComputerSelectorScanner}
                filemenusub.append(new gui.MenuItem({ label: "Recherche d'ordinateurs ...", click: showScanDialog }));
                // ###END###{ComputerSelectorScanner}
                // ###BEGIN###{MeshServerConnect}
                filemenusub.append(new gui.MenuItem({ type: 'separator' }));
                filemenusub.append(new gui.MenuItem({ label: "Se connecter à MeshCentral ...", click: showMeshCentralConnectDialog }));
                // ###END###{MeshServerConnect}
                seperator = true;
            }
            // ###BEGIN###{MeshServerConnect}
            } else {
                filemenusub.append(new gui.MenuItem({ label: "Se déconnecter de MeshCentral", click: meshCentralDisconnect }));
                seperator = true;
            }
            // ###END###{MeshServerConnect}
            // ###BEGIN###{USBSetup}
            if (x == 102) {
                // Setup.bin Editor
                filemenusub.append(new gui.MenuItem({ label: "Nouveau...", click: usb_newSetupBin }));
                filemenusub.append(new gui.MenuItem({ label: "Charger Setup.bin ...", click: NW_LoadSetupBin }));
                filemenusub.append(new gui.MenuItem({ label: "Enregistrez Setup.bin ...", click: usb_saveSetupBin }));
                seperator = true;
            }
            // ###END###{USBSetup}

            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer == null) {
            // ###END###{MeshServerConnect}
            if (x >= 101 && x <= 104) {
                // Tools
                toolsmenu = new gui.MenuItem({ label: "Outils" });
                var toolsmenusub = new gui.Menu();
                toolsmenusub.append(new gui.MenuItem({ label: "Gestion d'ordinateur", click: NW_ComputerManagement, type: 'checkbox', checked: (x == 101) }));
                // ###BEGIN###{CertificateManager}
                toolsmenusub.append(new gui.MenuItem({ label: "Gestionnaire de certificats", click: NW_CertificateManager, type: 'checkbox', checked: (x == 103) }));
                // ###END###{CertificateManager}
                // ###BEGIN###{USBSetup}
                toolsmenusub.append(new gui.MenuItem({ label: "Gestionnaire Setup.bin", click: NW_SetupBinEditor, type: 'checkbox', checked: (x == 102) }));
                // ###END###{USBSetup}
                // ###BEGIN###{SessionRecording}
                toolsmenusub.append(new gui.MenuItem({ label: "Lecteur de session", click: NW_SessionPlayer, type: 'checkbox', checked: (x == 104) }));
                // ###END###{SessionRecording}
                toolsmenu.submenu  = toolsmenusub;
            }
            // ###BEGIN###{Scripting}
            // ###BEGIN###{!Look-BrandedCommander}
            if (x == 101) {
                // Batch Scripting
                scriptmenu = new gui.MenuItem({ label: "Scénario" });
                var scriptmenusub = new gui.Menu();
                if (computersRunningScripts > 0) {
                    scriptmenusub.append(new gui.MenuItem({ label: "Arrêter tous les scripts", click: mscript_runScriptDlg }));
                } else {
                    scriptmenusub.append(new gui.MenuItem({ label: "Démarrer le script ...", click: mscript_runScriptDlg }));
                }
                scriptmenu.submenu  = scriptmenusub;
            }
            if (x >= 0 && x < 100) {
                // Computer Scripting
                scriptmenu = new gui.MenuItem({ label: "Scénario" });
                var scriptmenusub = new gui.Menu();
                if (scriptstate) {
                    scriptmenusub.append(new gui.MenuItem({ label: "Arrêter le script", click: script_Stop }));
                } else {
                    scriptmenusub.append(new gui.MenuItem({ label: "Démarrer le script ...", click: script_runScriptDlg }));
                }
                scriptmenu.submenu  = scriptmenusub;
            }
            // ###END###{!Look-BrandedCommander}
            // ###END###{Scripting}

            if (x == 101) {
                // Security
                securitymenu = new gui.MenuItem({ label: "Sécurité" });
                var securitymenusub = new gui.Menu();
                securitymenusub.append(new gui.MenuItem({ label: "Ignorer le certificat TLS", click: NW_ChangeTlsSecurityMode0, type: 'checkbox', checked: (NW_TlsSecurityMode == 0) }));
                securitymenusub.append(new gui.MenuItem({ label: "Afficher le certificat TLS et la broche", click: NW_ChangeTlsSecurityMode1, type: 'checkbox', checked: (NW_TlsSecurityMode == 1) }));
                securitymenusub.append(new gui.MenuItem({ type: 'separator' }));
                NW_SkipTlsHostnameMenuItem = new gui.MenuItem({ label: "Ignorer la vérification du nom d'hôte TLS", click: NW_SkipTlsHostnameCheck0, type: 'checkbox', checked: (NW_SkipTlsHostnameCheck == 1) })
                securitymenusub.append(NW_SkipTlsHostnameMenuItem);
                securitymenu.submenu  = securitymenusub;
            }
            // ###BEGIN###{MeshServerConnect}
            }
            // ###END###{MeshServerConnect}

            if (x >= 0 && x < 100 && disconnecturl != 'none' && disconnecturl != 'close') {
                // Computer screen
                filemenusub.append(new gui.MenuItem({ label: "Déconnecter", click: disconnect }));
                seperator = true;
            }
            
            // Explicit exit action not required on Mac. The MacBuiltin menu includes native option to quit application (Quit)
            if (os.platform() != 'darwin') {
                if (seperator == true) filemenusub.append(new gui.MenuItem({ type: 'separator' }));
                filemenusub.append(new gui.MenuItem({ label: "Sortie", click: NW_Exit }));
            }

            filemenu.submenu  = filemenusub;
            if (x == 13) {
                // Terminal
                toolsmenu = new gui.MenuItem({ label: "Terminal" });
                var toolsmenusub = new gui.Menu();
                if (terminal.State == 0) {
                    toolsmenusub.append(new gui.MenuItem({ label: "Relier", click: connectTerminal }));
                } else {
                    toolsmenusub.append(new gui.MenuItem({ label: "Déconnecter", click: connectTerminal }));
                }
                // ###BEGIN###{FileSaver}
                toolsmenusub.append(new gui.MenuItem({ type: 'separator' }));
                if (terminal.m.capture == null) {
                    // ###BEGIN###{!TerminalReplay}
                    toolsmenusub.append(new gui.MenuItem({ label: "Commencer la capture", click: terminalCaptureToggle }));
                    // ###END###{!TerminalReplay}
                    // ###BEGIN###{TerminalReplay}
                    if (terminalReplayTimer == null) {
                        toolsmenusub.append(new gui.MenuItem({ label: "Commencer la capture", click: terminalCaptureToggle }));
                        toolsmenusub.append(new gui.MenuItem({ label: "Rejouer la capture", click: terminalReplay }));
                    } else {
                        toolsmenusub.append(new gui.MenuItem({ label: "Arrêter la relecture", click: terminalReplay }));
                    }
                    // ###END###{TerminalReplay}
                } else {
                    toolsmenusub.append(new gui.MenuItem({ label: "Arrêter la capture", click: terminalCaptureToggle }));
                }
                // ###END###{FileSaver}
                toolsmenu.submenu  = toolsmenusub;
            }
            if (x == 14) {
                // Desktop
                toolsmenu = new gui.MenuItem({ label: "Bureau" });
                var toolsmenusub = new gui.Menu();
                if (desktop.State == 0) {
                    toolsmenusub.append(new gui.MenuItem({ label: "Relier", click: connectDesktop }));
                } else {
                    toolsmenusub.append(new gui.MenuItem({ label: "Déconnecter", click: connectDesktop }));
                }
                toolsmenusub.append(new gui.MenuItem({ type: 'separator' }));
                toolsmenusub.append(new gui.MenuItem({ label: "Réglages", click: showDesktopSettings }));
                toolsmenu.submenu  = toolsmenusub;
            }

            // Language menu
            var languagemenu = new gui.MenuItem({ label: "Langue" });
            var languagesubmenu = new gui.Menu();
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'en'), label: "Anglais", click: function () { window.location.href = 'commander.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'zh-chs'), label: "Chinois simplifié)", click: function () { window.location.href = 'commander_zh-chs.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'nl'), label: "néerlandais", click: function () { window.location.href = 'commander_nl.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'fr'), label: "français", click: function () { window.location.href = 'commander_fr.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'de'), label: "allemand", click: function () { window.location.href = 'commander_de.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'it'), label: "italien", click: function () { window.location.href = 'commander_it.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'ja'), label: "Japonais", click: function () { window.location.href = 'commander_ja.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'pt'), label: "Portugais", click: function () { window.location.href = 'commander_pt.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'ru'), label: "russe", click: function () { window.location.href = 'commander_ru.htm'; } }));
            languagesubmenu.append(new gui.MenuItem({ type: 'checkbox', checked: (document.documentElement.lang == 'es'), label: "Espagnol", click: function () { window.location.href = 'commander_es.htm'; } }));
            languagemenu.submenu = languagesubmenu;

            var helpmenu = new gui.MenuItem({ label: "Aidez-moi" });
            var helpmenusub = new gui.Menu();
            // ###BEGIN###{Look-Commander}
            var checkForUpdateCheck = false;
            try { checkForUpdateCheck = (localStorage.getItem('checkForUpdate') == 'false') ? false : true; } catch (ex) {}
            NW_UpdateMenuItem = new gui.MenuItem({ type: 'checkbox', checked: checkForUpdateCheck, label: "Vérifier les mises à jour", click: NW_CheckForUpdateMenu })
            helpmenusub.append(NW_UpdateMenuItem);
            // ###END###{Look-Commander}
            // ###BEGIN###{Look-BrandedCommander}
            var checkForUpdateCheck = false;
            try { checkForUpdateCheck = (localStorage.getItem('checkForUpdate') == 'false') ? false : true; } catch (ex) { }
            NW_UpdateMenuItem = new gui.MenuItem({ type: 'checkbox', checked: checkForUpdateCheck, label: "Vérifier les mises à jour", click: NW_CheckForUpdateMenu })
            helpmenusub.append(NW_UpdateMenuItem);
            // ###END###{Look-BrandedCommander}
            // ###BEGIN###{ComputerSelectorScanner}
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer == null) {
            // ###END###{MeshServerConnect}
            var amtPresenceScan = true;
            try { amtPresenceScan = (localStorage.getItem('scanForComputers') == 'false') ? false : true; } catch (ex) { }
            NW_AmtScanMenuItem = new gui.MenuItem({ type: 'checkbox', checked: amtPresenceScan, label: "Rechercher la présence", click: NW_AmtScanMenu })
            helpmenusub.append(NW_AmtScanMenuItem);
            if (amtPresenceScan == true) { globalAmtScanner.start(); }
            // ###BEGIN###{MeshServerConnect}
            }
            // ###END###{MeshServerConnect}
            // ###END###{ComputerSelectorScanner}
            helpmenusub.append(new gui.MenuItem({ label: "Réinitialiser", click: NW_Reload }));
            if (urlvars['debug']) { helpmenusub.append(new gui.MenuItem({ label: "Afficher le débogage ...", click: NW_Debug })); }
            // ###BEGIN###{Look-ISDU}
            helpmenusub.append(new gui.MenuItem({ type: 'separator' }));
            helpmenusub.append(new gui.MenuItem({ label: "About...", click: WM_About }));
            // ###END###{Look-ISDU}
            // ###BEGIN###{Look-BrandedCommander}
            helpmenusub.append(new gui.MenuItem({ type: 'separator' }));
            helpmenusub.append(new gui.MenuItem({ label: "About...", click: WM_About }));
            // ###END###{Look-BrandedCommander}
            helpmenu.submenu  = helpmenusub;
            mainmenu.append(filemenu);
            if (toolsmenu != null) mainmenu.append(toolsmenu);
            if (scriptmenu != null) mainmenu.append(scriptmenu);
            if (securitymenu != null) mainmenu.append(securitymenu);
            mainmenu.append(languagemenu);
            mainmenu.append(helpmenu);
            gui.Window.get().menu = mainmenu;
        }

        function NW_Exit() {
            require('nw.gui').Window.get().close(); // Closes only the current window.
            //require('nw.gui').App.quit(); // Closes all instances of the app.
        }
        function NW_Reload() { require('nw.gui').Window.get().reloadIgnoringCache(); }
        function NW_Debug() { require('nw.gui').Window.get().showDevTools(); }

        function NW_ChangeTlsSecurityMode0() { NW_TlsSecurityMode = 0; try { localStorage.setItem('TlsSecurityMode', NW_TlsSecurityMode); } catch (ex) { } NW_SetupMainMenu(currentView); }
        function NW_ChangeTlsSecurityMode1() { NW_TlsSecurityMode = 1; try { localStorage.setItem('TlsSecurityMode', NW_TlsSecurityMode); } catch (ex) { } NW_SetupMainMenu(currentView); }
        function NW_SkipTlsHostnameCheck0() { NW_SkipTlsHostnameCheck = NW_SkipTlsHostnameMenuItem.checked ? 1 : 0; try { localStorage.setItem('SkipTlsHostnameCheck', NW_SkipTlsHostnameCheck); } catch (ex) { } NW_SetupMainMenu(currentView); }
        function NW_LoadComputers() {
            var chooser = Q('idx_d17computerlistfile');
            if (chooser.getAttribute('eventset') != 1) {
                chooser.setAttribute('eventset', '1');
                chooser.addEventListener('change', NW_LoadComputersEx, false);
            }
            chooser.value = null;
            chooser.click();
        }
        function NW_LoadComputersEx(evt) {
            var reader = new FileReader();
            reader.onload = function(file) { onComputerListRead(file, Q('idx_d17computerlistfile').files[0].name); }
            reader.readAsBinaryString(this.files[0]);
        }

        function NW_SaveComputers() { saveComputerList(); }
        function NW_ComputerManagement() { toolmenuclick(-1); go(101); }
        // ###BEGIN###{CertificateManager}
        function NW_CertificateManager() { toolmenuclick(-1); go(103); }
        // ###END###{CertificateManager}
        function NW_SetupBinEditor() { toolmenuclick(-1); go(102); }
        // ###BEGIN###{SessionRecording}
        function NW_SessionPlayer() { toolmenuclick(-1); go(104); }
        // ###END###{SessionRecording}

        function NW_LoadSetupBin() {
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('accept', '.bin');
            chooser.addEventListener('change', NW_LoadSetupBinEx, false);
            chooser.value = null;
            chooser.click();
        }
        function NW_LoadSetupBinEx() {
            var reader = new FileReader();
            reader.onload = function(file) { usb_onSetupBinRead(file); }
            reader.readAsBinaryString(this.files[0]);
        }

        // ###BEGIN###{Look-ISDU}
        function WM_About() {
            var x = { 'position': 'center', 'focus': true, 'frame': true, 'icon': 'favicon.png', 'width': 520, 'height': 320 };
            if (process.version == 'v1.2.0') x['toolbar'] = false;
            require('nw.gui').Window.open('about.htm', x);
        }
        // ###END###{Look-ISDU}

        // ###BEGIN###{Look-BrandedCommander}
        function WM_About() {
            var x = { 'position': 'center', 'focus': true, 'frame': true, 'icon': 'favicon.png', 'width': 520, 'height': 320 };
            if (process.version == 'v1.2.0') x['toolbar'] = false;
            require('nw.gui').Window.open('about.htm', x);
        }
        // ###END###{Look-BrandedCommander}

// ###END###{Mode-NodeWebkit}

// ###BEGIN###{ComputerSelector}
        // Load the list of computers from the server
        function loadServerComputerList() {
            var request = new XMLHttpRequest();
            request.onload = function() {
                if (request.status >= 200 && request.status < 400) {
                    // Success
                    var serverComputerList = JSON.parse(request.responseText);
                    if (serverComputerList && serverComputerList != null && serverComputerList instanceof Array) {
                        currentcomputer = null;
                        computerlist = [];
                        for (var i in serverComputerList) {
                            var computer = serverComputerList[i];
                            if (computer['host']) {
                                computer.checked = false;
                                if (!computer['h']) computer['h'] = Math.random(); // If 'h' handle is not present, create one.
                                if (!computer['tls']) computer['tls'] = 0; // If TLS is not present, assume 0.
                                computerlist.push(computer);
                            }
                        }
                        updateComputerList();
                    }
                } else {
                    console.log('Failed to get server computer list');
                }
            };

            request.onerror = function() {
                console.log('Failed to get server computer list');
            };

            // ###BEGIN###{ComputerSelector-Remote}
            request.open('GET', 'webrelay.ashx?action=getcomputerlist', true);
            // ###END###{ComputerSelector-Remote}
            // ###BEGIN###{ComputerSelector-Local}
            request.open('GET', urlvars['connect'], true);
            // ###END###{ComputerSelector-Local}
            request.send();
        }
// ###END###{ComputerSelector}

// ###BEGIN###{Mode-LMS}
        // Called when the LMS control channel changes state
        function lmsChangedState(sender, state)
        {
            //console.log("LMS Control Channel State: " + state);
            if (state == 0) { 
                setDialogMode();
                QV('id_lmsToolBarContent', false);
                QH('id_lmsData', '<div style=text-align:center;padding-top:20px>' + "MicroLMS disconnected." + '<div>');
                QH('id_lmsData2', '');
            } else if (state == 2) { QV('id_lmsToolBarContent', true); lmsRefresh(); }
        }

        function lmsLogin() { window.location.href = '/authindex.html'; }

        var lmsProvisioningStates = ["Pre-Provisioning", "In-Provisioning", "Post-Provisioning"];
        var lmsProvisioningModes = ["Aucun", "Enterprise Mode", "Small Buisness Mode", "Remote Assistance Mode"];
        var lmsMeInfo = null;
        var lmsTemp = null;
        var lmsNotifications = null;

        // Called when data is received on the LMS control channel
        function lmsOnData(sender, data)
        {
            var cmdid = ReadShortX(data, 0);
            //console.log("LMS Control Channel Data: " + data + ", cmdid:" + cmdid);

            switch (+cmdid) {
                case 1: { // ME Information
                    //console.log(data.substring(2));
                    var meinfo = JSON.parse(data.substring(2));
                    QV('id_lmsLoginButton', meinfo['LoginMode'] == 1);

                    // If Intel AMT is in-between states, reload data in a few seconds.
                    if ((meinfo['TrustedHashes'] != null) && (meinfo['ProvisioningMode'] == -858993460)) {
                        QV('id_lmsConfigureButton', false);
                        QV('id_lmsActivateButton', false);
                        QV('id_lmsDeactivateButton', false);
                        setTimeout(lmsRefresh, 1000);
                        return;
                    }

                    lmsMeInfo = meinfo;
                    if (meinfo['ProvisioningState'] == null) {
                        QH('id_lmsData', '<div style=text-align:center;padding-top:20px>' + "Intel&reg; AMT not found" + '<div>');
                        QH('id_lmsData2', '');
                    } else {
                        meinfo['Flags'] = +meinfo['Flags'];

                        var x = '<h2>' + "Current Status" + '</h2>';
                        x += TableStart();
                        if (meinfo['ProvisioningState'] != 2) {
                            x += TableEntry("Activation state", lmsProvisioningStates[meinfo['ProvisioningState']]);
                        } else {
                            if (meinfo['Flags'] & 2) { x += TableEntry("Activation state", "Activated in Client Control Mode"); }
                            else if (meinfo['Flags'] & 4) { x += TableEntry("Activation state", "Activated in Admin Control Mode"); }
                            else { x += TableEntry("Activation state", "Activated, " + lmsProvisioningModes[meinfo['ProvisioningMode']]); }
                        }
                        x += TableEntry("Intel&reg; AMT version", addLink(meinfo['Versions']['AMT'], 'lmsShowVersionsDlg()'));
                        if (meinfo['MeiVersion'] != null) { x += TableEntry("Intel&reg; MEI driver version", meinfo['MeiVersion']); }
                        x += TableEnd();

                        if (meinfo['ProvisioningState'] != 2) {
                            x += '<h2>' + "Activation Information" + '</h2>';
                            x += TableStart();
                            if (meinfo['DnsSuffix']) {
                                x += TableEntry("Trusted DNS suffix", meinfo['DnsSuffix']);
                            } else {
                                x += TableEntry("Trusted DNS suffix", '<i>' + "Not Set" + '</i>');
                            }
                            if (meinfo['TrustedHashes'] != null) {
                                if (meinfo['TrustedHashes'].length == 1) {
                                    x += TableEntry("Trusted hashes", addLink(meinfo['TrustedHashes'].length + ' hash', 'lmsShowTrustedHashesDlg()'));
                                } else {
                                    x += TableEntry("Trusted hashes", addLink(meinfo['TrustedHashes'].length + ' hashes', 'lmsShowTrustedHashesDlg()'));
                                }
                            }
                            x += TableEnd();
                        }

                        QH('id_lmsData', x);
                        QV('id_lmsData2', true);
                        lmsNotifications = meinfo['Notifications'].reverse();
                        lmsRefreshNotifications();
                        QV('id_lmsConfigureButton', (meinfo['ProvisioningState'] == 2)); // Only display the "Login..." button if Intel AMT is in post-provisioning state.
                        QV('id_lmsActivateButton', (meinfo['ProvisioningState'] == 0) && (meinfo['LoginMode'] >= 2)); // Only display the "Activate..." button if Intel AMT is in pre-provisioning state and we are adrministrator.
                        QV('id_lmsDeactivateButton', (meinfo['ProvisioningState'] == 2) && (meinfo['Flags'] & 2) && (meinfo['LoginMode'] >= 2)); // Only display the "Deactivate..." button if Intel AMT is in port-provisioning state & in client control mode & we are adrministrator.
                    }
                    break;
                }
                case 2: { // Intel ME Un-Provisioning
                    lmsDeactivateX2(ReadIntX(data, 2));
                    break;
                }
                case 3: { // Intel ME System Account Information
                    var status = ReadIntX(data, 2);
                    if (status != 0) {
                        messagebox("Activation Intel&reg; AMT", format("Failed to get account information, status {0}", status));
                    } else {
                        var meuser = data.substring(6, data.indexOf('\0', 6));
                        var mepass = data.substring(39, data.indexOf('\0', 39));
                        QH('id_dialogMessage', "Fetching activation status...");
                        wsstack = WsmanStackCreateService("localhost", 16992, meuser, mepass, false);
                        amtstack = AmtStackCreateService(wsstack);
                        amtstack.onProcessChanged = onProcessChanged;
                        amtstack.BatchEnum(null, ['*AMT_GeneralSettings', '*IPS_HostBasedSetupService'], lmsActivationX1);
                    }
                    break;
                }
                case 9: { // New notification
                    var notification = JSON.parse(data.substring(2));
                    if (lmsNotifications == null) { lmsNotifications = []; }
                    lmsNotifications.unshift(notification);
                    lmsRefreshNotifications();
                    if ((notification.code == 'iAMT0055-0') || (notification.code == 'iAMT0055-1') || (notification.code == 'iAMT0055-2')) { setDialogMode(); lmsRefresh(); }
                    break;
                }
            }
        }

        function lmsRefreshNotifications() {
            var x = '<h2>' + "Notifications" + '</h2>' + TableStart();
            if (lmsNotifications && lmsNotifications.length > 0) {
                for (var i in lmsNotifications) {
                    var n = lmsNotifications[i], v = n.str;
                    if (n.code != 'iAMT0050-32') {
                        if (v.indexOf('User Notification Alert - ') == 0) { v = v.substring(26); }
                        x += TableEntry(new Date(n.date).toLocaleString(), v);
                    }
                }
            } else {
                x += '<tr><td style=padding:8px><i>' + "No notifications found." + '</i><td>';
            }
            x += TableEnd();
            QH('id_lmsData2', x);
        }

        function lmsActivationX1(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Activation Intel&reg; AMT", format("Failed to fetch activation status, status {0}", status));
            } else if (responses['IPS_HostBasedSetupService'].response['AllowedControlModes'].length != 2) {
                messagebox("Activation Intel&reg; AMT", "Client control mode activation not allowed");
            } else {
                lmsTemp = responses['AMT_GeneralSettings'].response;
                amtstack.IPS_HostBasedSetupService_Setup(2, rstr2hex(rstr_md5('admin:' + responses['AMT_GeneralSettings'].response['DigestRealm'] + ':' + d4password.value)), null, null, null, null, lmsActivationX2);
            }
        }

        function lmsActivationX2(stack, name, response, status) {
            if (status != 200 || response.Body['ReturnValue'] != 0) {
                messagebox("Activation Intel&reg; AMT", format("Failed activation, status {0}", status));
            } else {
                setDialogMode();
                lmsRefresh();
                lmsTemp['HostName'] = lmsMeInfo['OsHostname']; // Set the OS hostname
                // TODO: Also set the local FQDN if we can get it from LMS
                wsstack = WsmanStackCreateService('localhost', 16992, 'admin', d4password.value, false);
                amtstack = AmtStackCreateService(wsstack);
                amtstack.onProcessChanged = onProcessChanged;
                amtstack.Put('AMT_GeneralSettings', lmsTemp, function() { }, 0, 1);
            }
        }

        function lmsDeactivate() {
            if (xxdialogMode || lms.State != 2) return;
            QH('id_dialogMessage', "Confirm Intel&reg; AMT deactivation?");
            setDialogMode(1, "Intel&reg; AMT Deactivation", 3, lmsDeactivateX1);
        }

        function lmsDeactivateX1() {
            statusbox("Intel&reg; AMT Deactivation", "Deactivating Intel&reg; AMT...");
            lms.SendCmd(2, IntToStrX(1)); // Send request for deactivation
        }

        function lmsDeactivateX2(status) {
            if (status != 0) {
                messagebox("Intel&reg; AMT Deactivation", format("Failed deactivation, status ", status));
            } else {
                QH('id_lmsData', "Please wait for deactivation...");
                QV('id_lmsData2', false);
                setDialogMode();
                lmsRefresh();
            }
        }

        // Refresh button on the UI
        function lmsRefresh() {
            if (lms.State != 2) return;
            lms.SendCmd(1, ''); // Send the request basic information command
        }

        // Configure button on the UI
        function lmsConfigure() {
            if (xxdialogMode) return;
            setDialogMode(4, "Intel&reg; AMT Login", 3, function () { lmsConfigureLogin(); });
            //d4username.readOnly = false;
            d4username.disabled = false;
            if (d4username.value == 'admin') d4username.value = '';
            inputBoxFocus('d4username');
            lmsUpdateLoginDialog();
        }

        // Called when the user hits OK on the login dialog
        function lmsConfigureLogin() {
            var user = d4username.value;
            if (user == '') user = 'admin';
            connect('localhost', 16992, user, d4password.value, 0);
        }

        // Activate button on the UI
        function lmsActivate() {
            if (xxdialogMode|| lms.State != 2) return;
            setDialogMode(4, "Activation Intel&reg; AMT", 3, function () { lmsActivateEx(); });
            //d4username.readOnly = true;
            d4username.disabled = true;
            d4username.value = 'admin';
            inputBoxFocus('d4password');
            lmsUpdateLoginDialog();
        }

        // Go head with Intel AMT client control mode activation
        function lmsActivateEx()
        {
            lms.SendCmd(3); // Send request for account information
            statusbox("Activation Intel&reg; AMT", "Fetching Account Information...");
        }

        // Called each time something changes in the login dialog
        function lmsUpdateLoginDialog(e, d) {
            var ok = passwordcheck(d4password.value);
            QE('idx_dlgOkButton', ok);
            if (e != null && e.keyCode == 13 && d == 1) inputBoxFocus('d4password');
            if (ok == true && e != null && e.keyCode == 13 && d == 2) dialogclose(1);
        }

        var lmsHashArgStrings = ["MD5", "SHA1", "SHA256", "SHA512"];
        function lmsShowTrustedHashesDlg() {
            // {\"AC\":%d,\"DF\":%d,\"AL\":%d,\"NA\":\"%s\",\"HA\":\"%s\"}"

            var x = '<div style=max-height:240px;overflow-y:scroll>' + TableStart();
            for (var i in lmsMeInfo['TrustedHashes'])
            {
                //x += '<b>' + lmsMeInfo['TrustedHashes'][i]['Name'] + '</b><br><span style=font-size:10px>' + lmsHashArgStrings[lmsMeInfo['TrustedHashes'][i]['HashAlgorithm']] + (lmsMeInfo['TrustedHashes'][i]['Active'] == 1?", Active":'') + (lmsMeInfo['TrustedHashes'][i]['Default'] == 1?", Default":'') + '</span><br><span style=font-size:10px>' + lmsMeInfo['TrustedHashes'][i]['Hash'] + '</span><br><br>';
                x += TableEntry('<b>' + lmsMeInfo['TrustedHashes'][i]['Name'] + '</b><br><span style=font-size:10px>' + lmsHashArgStrings[lmsMeInfo['TrustedHashes'][i]['HashAlgorithm']] + (lmsMeInfo['TrustedHashes'][i]['Active'] == 1?", Active":'') + (lmsMeInfo['TrustedHashes'][i]['Default'] == 1?", Default":'') + '</span><br><span style=font-size:8px>' + lmsMeInfo['TrustedHashes'][i]['Hash'] + '</span>', '');
            }
            x += TableEnd() + '</div>';
            messagebox("Intel&reg; AMT Trusted Hashes", x);
        }

        function lmsShowVersionsDlg() {
            var x = TableStart();
            x += TableEntry("Intel&reg; AMT", lmsMeInfo['Versions']['AMT']);
            if (lmsMeInfo['MeiVersion'] != null) { x += TableEntry("Intel&reg; MEI driver", lmsMeInfo['MeiVersion']); }
            for (var i in lmsMeInfo['Versions']) { if (i != 'AMT') x += TableEntry(i, lmsMeInfo['Versions'][i]); }
            x += TableEnd();
            messagebox("Intel&reg; AMT Versions", x);
        }

// ###END###{Mode-LMS}

// ###BEGIN###{Mode-MeshCentral2}
        function connectButtonfunction() {
            if (!wsstack || wsstack.socketState == 0) { meshcentral2credCallback(); } else { disconnect(); }
        }

        function connectButtonfunctionEx() {
            currentMeshNode = parent.getCurrentNode();
            connect(currentMeshNode._id, 16992, null, null, 0);
            Q('xconnectbutton1').value = "Déconnecter";
        }

        function getCurrentMeshNode() { return currentMeshNode; }
        function setConnectionState(isConnectable) { QE('xconnectbutton1', isConnectable); if (isConnectable == false) { disconnect(); } }
        function setFrameHeight(height) {
            //console.log('setFrameHeight', height);
            //QS('entireBody').height = height;
        }
        function setAuthCallback(updateAmtCredentials) { meshcentral2credCallback = updateAmtCredentials; }
        function setUrlVar(name, value) { if (!urlvars) { urlvars = {}; } urlvars[name] = value; }
// ###END###{Mode-MeshCentral2}

        function cleanup() {
            // ###BEGIN###{Terminal}
            // ###BEGIN###{FileSaver}
            // ###BEGIN###{!Mode-NodeWebkit}
            idx_terminalCaptureButton.value = "Commencer la capture";
            // ###END###{!Mode-NodeWebkit}
            if (terminal.m.capture) delete terminal.m.capture;
            // ###END###{FileSaver}
            terminal.Stop();
            // ###END###{Terminal}
            // ###BEGIN###{Desktop}
            desktop.disconnectCode = 0;
            desktop.Stop();
            // ###END###{Desktop}
        }

        function handleKeyUp(e) {
            if (xxdialogMode) return;
            // ###BEGIN###{ComputerSelector}
            // ###BEGIN###{ComputerSelector-Local}
            if (currentView == 101) {
                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer == null) {
                // ###END###{MeshServerConnect}
                    if (e.keyCode == 45) { addComputer(); } // Insert key
                    if (e.keyCode == 46) { deleteComputers(); } // Delete key
                // ###BEGIN###{MeshServerConnect}
                }
                // ###END###{MeshServerConnect}
                if ((e.keyCode == 65) && (e.ctrlKey == true)) { selectAllComputers(); } // Select all
                if (e.keyCode == 13) { if (computersRunningScripts == 0) { computerConnect(event, currentcomputer.h); } } // Enter key
                if ((e.keyCode == 8) && !filterFocus) { var x = Q('computerFilter').value; Q('computerFilter').value = (x.substring(0, x.length - 1)); computerFilterFunc(); }
                if (e.keyCode == 27) { Q('computerFilter').value = ''; computerFilterFunc(); }
            }
            // ###END###{ComputerSelector-Local}
            // ###BEGIN###{ComputerSelector-Remote}
            if (currentView == 101) {
                if ((e.keyCode == 65) && (e.ctrlKey == true)) { selectAllComputers(); } // Select all
            }
            // ###END###{ComputerSelector-Remote}
            // ###END###{ComputerSelector}
            // ###BEGIN###{CertificateManager}
            if (currentView == 103) {
                //if (e.keyCode == 45) { addComputer(); } // Insert key
                if (e.keyCode == 46) { cert_deleteCertificates(); } // Delete key
                //if ((e.keyCode == 65) && (e.ctrlKey == true)) { selectAllCertificates(); } // Select all
            }
            // ###END###{CertificateManager}
            // ###BEGIN###{Desktop}
            // ###BEGIN###{!DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (!Q('id_DeskVO').checked) { return desktop.m.handleKeyUp(e); } }
            // ###END###{!DesktopInband}
            // ###BEGIN###{DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (Q('id_DeskVO').checked) return; if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.handleKeyUp(e); desktop.m.sendKeepAlive(); } else { return desktop.m.handleKeyUp(e); } }
            // ###END###{DesktopInband}
            // ###END###{Desktop}
            // ###BEGIN###{Terminal}
            if (currentView == 13 && terminal.State == 3) return terminal.m.TermHandleKeyUp(e);
            // ###END###{Terminal}
        }

        function handleKeyDown(e) {
            //console.log('handleKeyDown', e);
            if (xxdialogMode) return;
            // ###BEGIN###{Desktop}
            // ###BEGIN###{!DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (!Q('id_DeskVO').checked) { return desktop.m.handleKeyDown(e); } }
            // ###END###{!DesktopInband}
            // ###BEGIN###{DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (Q('id_DeskVO').checked) return; if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.handleKeyDown(e); desktop.m.sendKeepAlive(); } else { return desktop.m.handleKeyDown(e); } }
            // ###END###{DesktopInband}
            // ###END###{Desktop}
            // ###BEGIN###{Terminal}
            if (currentView == 13 && terminal.State == 3) return terminal.m.TermHandleKeyDown(e);
            // ###END###{Terminal}
            // ###BEGIN###{ComputerSelector-Local}
            if (currentView == 101) {
                if (e.keyCode == 38) { var selectprev = null; for (var y in computerlist) { if (currentcomputer.h == computerlist[y].h) { if (selectprev != null) { computerSelect(null, selectprev); } } else { selectprev = computerlist[y].h; } } } // Up key
                if (e.keyCode == 40) { var selectnext = 0; for (var y in computerlist) { if (selectnext == 1) { selectnext = 2; computerSelect(null, computerlist[y].h); } else { if (currentcomputer.h == computerlist[y].h) { selectnext = 1; } } } } // Down key
            }
            // ###END###{ComputerSelector-Local}
        }

        function handleKeyPress(e) {
            //console.log('handleKeyPress', e);
            if (xxdialogMode) return;
            // ###BEGIN###{ComputerSelector-Local}
            if (currentView == 101) {
                if ((!filterFocus) && (e.keyCode != 0)) { Q('computerFilter').value = ((Q('computerFilter').value + String.fromCharCode(e.keyCode))); computerFilterFunc(); }
            }
            // ###END###{ComputerSelector-Local}
            // ###BEGIN###{Desktop}
            // ###BEGIN###{!DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (!Q('id_DeskVO').checked) { return desktop.m.handleKeys(e); } }
            // ###END###{!DesktopInband}
            // ###BEGIN###{DesktopInband}
            if (currentView == 14 && desktop.State == 3) { if (Q('id_DeskVO').checked) return; if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.handleKeys(e); desktop.m.sendKeepAlive(); } else { return desktop.m.handleKeys(e); } }
            // ###END###{DesktopInband}
            // ###END###{Desktop}
            // ###BEGIN###{Terminal}
            if (currentView == 13 && terminal.State == 3) return terminal.m.TermHandleKeys(e);
            // ###END###{Terminal}
            // ###BEGIN###{SessionRecording}
            if (currentView == 104) {
                if (e.keyCode == 32) { srec_togglePause(); haltEvent(e); }
                if (e.keyCode == 49) { Q('srec_PlaySpeed').value = 4; haltEvent(e); }
                if (e.keyCode == 50) { Q('srec_PlaySpeed').value = 2; haltEvent(e); }
                if (e.keyCode == 51) { Q('srec_PlaySpeed').value = 1; haltEvent(e); }
                if (e.keyCode == 52) { Q('srec_PlaySpeed').value = 0.5; haltEvent(e); }
                if (e.keyCode == 53) { Q('srec_PlaySpeed').value = 0.25; haltEvent(e); }
                if (e.keyCode == 54) { Q('srec_PlaySpeed').value = 0.1; haltEvent(e); }
                if (e.keyCode == 48) { srec_pause(); srec_restart(); haltEvent(e); }
            }
            // ###END###{SessionRecording}
        }

        var connectFunc = null;
        var connectFuncTag = null;
        function connect(host, port, user, pass, tls, func, functag) {
            go(0);
            fullscreenonly = false;
            connectFunc = func;
            connectFuncTag = functag;

            // ###BEGIN###{Desktop}
            if (urlvars['kvm'] == 1) { go(14); }
            if ((urlvars['kvmfull'] == 1) || (urlvars['kvmonly'] == 1)) { go(14); deskToggleFull(urlvars['kvmonly'] == 1); }
            // ###END###{Desktop}
            // ###BEGIN###{Terminal}
            if (urlvars['sol'] == 1) { go(13); }
            // ###END###{Terminal}

            // ###BEGIN###{Mode-NodeWebkit}
            var tlsoptions = {};
            // ###BEGIN###{CertificateManager}

            // Create a list of trusted certificates in PEM format
            var trustedCertStringsPem = [];
            for (var y in certificateStore) {
                var certificate = certificateStore[y];
                if (certificate['trusted'] == true) { trustedCertStringsPem.push('-----BEGIN CERTIFICATE-----\n' + certificate['certbin'] + '\n-----END CERTIFICATE-----\n'); }
            }
            tlsoptions.ca = trustedCertStringsPem;

            // Setup out console TLS authentication certificate
            var authcert = getTlsAuthCertificate();
            if (authcert != null) {
                tlsoptions.cert = forge.pki.certificateToPem(authcert['cert']);
                tlsoptions.key = forge.pki.privateKeyToPem(authcert['privateKey']);
            }

            // ###END###{CertificateManager}

            // ###BEGIN###{!MeshServerConnect}
            wsstack = WsmanStackCreateService(host, port, user, pass, tls, tlsoptions);
            // ###END###{!MeshServerConnect}
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                wsstack = WsmanStackCreateService(currentcomputer._id, null, null, null, 0, meshCentralServer);
            } else {
                wsstack = WsmanStackCreateService(host, port, user, pass, tls, tlsoptions);
            }
            // ###END###{MeshServerConnect}

            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            wsstack = WsmanStackCreateService(host, port, user, pass, tls);
            // ###END###{!Mode-NodeWebkit}
            amtstack = AmtStackCreateService(wsstack);
            amtstack.onProcessChanged = onProcessChanged;

            // Setup TLS checking
            // ###BEGIN###{Mode-NodeWebkit}
            wsstack.comm.xtlsSkipHostCheck = NW_SkipTlsHostnameCheck;
            if (NW_TlsSecurityMode == 0) { wsstack.comm.xtlsFingerprint = 0; }
            else { wsstack.comm.xtlsFingerprint = currentcomputer['tlscerthash'] ? currentcomputer['tlscerthash'] : currentcomputer['tlscerthash2']; }
            // ###END###{Mode-NodeWebkit}

            // Hide TLS indicator
            // ###BEGIN###{Mode-NodeWebkit}
            QV('tlsNotification1', false);
            QV('tlsNotification2', false);
            QV('tlsNotification3', false);
            QV('tlsNotification4', false);
            // ###END###{Mode-NodeWebkit}

            // Setup Digest Realm checking
            // ###BEGIN###{ComputerSelector}
            if (currentcomputer['digestrealm']) { wsstack.comm.digestRealmMatch = currentcomputer['digestrealm']; }
            // ###END###{ComputerSelector}

            // Hide most of the left menu options, we will see them as we load data
            for (var i = 2; i < 25; i++) { QV('go' + i, false); }
            QV('go8', true); // Network Settings
            // ###BEGIN###{Terminal}
            QV('go13', false); // Terminal
            // ###BEGIN###{!Mode-NodeWebkit}
            QE('TermWD', false);
            // ###END###{!Mode-NodeWebkit}
            // ###END###{Terminal}
            // ###BEGIN###{Desktop}
            //QV('go14', false); // Desktop
            // ###END###{Desktop}
            //QV('go15', false); // Audit Log
            // ###BEGIN###{WsmanBrowser}
            QV('go12', true); // WSMAN Browser
            // ###END###{WsmanBrowser}
            // ###BEGIN###{Certificates}
            //QV('go16', false); // Security Settings
            // ###END###{Certificates}
            // ###BEGIN###{RemoteAccess}
            //QV('go17', false); // Remote Access
            // ###END###{RemoteAccess}
            // ###BEGIN###{Scripting-Editor}
            QV('go20', true); // Scripting Editor
            // ###END###{Scripting-Editor}

            // ###BEGIN###{Storage}
            // ###BEGIN###{Mode-Firmware}
            //QH('storagelinks', '');
            // ###END###{Mode-Firmware}
            // ###END###{Storage}

            // Clear the displayed power state
            // ###BEGIN###{Terminal}
            QH('id_p13power', ''); // Terminal
            // ###END###{Terminal}
            // ###BEGIN###{Desktop}
            QH('id_p14power', ''); // Desktop
            // ###END###{Desktop}

            // Clear everything, make sure all connection state is reset.
            amtversion = amtversionmin = amtFirstPull = 0;
            amtsysstate = amtdeltatime = amtlogicalelements = HardwareInventory = undefined;
            amtPowerBootCapabilities = null;
            xxAccountFetch = 999;
            // ###BEGIN###{PowerControl}
            // ###BEGIN###{!Mode-MeshCentral2}

            if (!urlvars['norefresh']) { amtPowerPollTimer = setInterval(PullPowerState, 5000); }

            // ###END###{!Mode-MeshCentral2}
            // ###END###{PowerControl}

            // Show loading on all panels
            QH('id_TableSysStatus', LoadingHtml);
            // ###BEGIN###{NetworkSettings}
            QH('id_TableNetworkSettingsSpan', LoadingHtml);
            amtwirelessif = -1;
            // ###BEGIN###{Wireless}
            xxWireless = undefined;
            QH('id_TableWifi2', '');
            // ###END###{Wireless}
            // ###END###{NetworkSettings}
            // ###BEGIN###{HardwareInfo}
            QH('id_TableSysInfo', LoadingHtml);
            // ###END###{HardwareInfo}

            xxAccountAdminName = null;
            xxAccountRealmInfo = {};
            QH('id_TableUserAccounts', LoadingHtml);
            // ###BEGIN###{EventLog}
            eventmessages = null;
            QH('id_TableEventLog','');
            QH('id_TableEventLog2',LoadingHtml);
            // ###END###{EventLog}
            // ###BEGIN###{AuditLog}
            auditLog = null;
            QH('id_TableAuditLog1', '');
            QH('id_TableAuditLog2', LoadingHtml);
            // ###END###{AuditLog}
            // ###BEGIN###{Certificates}
            xxCertificates = null;
            QH('id_TableCerts', LoadingHtml);
            // ###END###{Certificates}
            // ###BEGIN###{WsmanBrowser}
            QH('id_wsresults', '');
            // ###END###{WsmanBrowser}
            // ###BEGIN###{IDER}
            iderStop();
            // ###END###{IDER}
            // ###BEGIN###{RemoteAccess}
            xxRemoteAccess = null;
            xxEnvironementDetection = null;
            xxCiraServers = null;
            xxUserInitiatedCira = null;
            xxRemoteAccessCredentiaLinks = null;
            xxMPSUserPass = null;
            xxPolicies = null;
            QH('id_TableRemoteAccess', LoadingHtml);
            // ###END###{RemoteAccess}
            // ###BEGIN###{AgentPresence}
            QH('id_TableSystemAgentPresence', LoadingHtml);
            // ###END###{AgentPresence}
            // ###BEGIN###{SystemDefense}
            xxSystemDefense = null;
            xxSystemDefenceLinkedPolicy = {};
            xxUpdatingDefenseStats = false;
            xxFilterStatistics = [{}, {}]; // Wired and wireless interface stats
            xxFilterStatisticsTimer = null;
            xxFilterStatisticsTimerActive = false;
            QH('id_TableSystemDefense', LoadingHtml);
            // ###END###{SystemDefense}
            // ###BEGIN###{Desktop}
            QE('id_DeskCAD', false);
            // ###BEGIN###{DesktopClipboard}
            QE('id_DeskKvmClipButton', false);
            // ###END###{DesktopClipboard}
            QE('DeskWD', false);
            QE('deskkeys', false);
            if (urlvars['kvmviewonly']) { QE('id_DeskVO', false); Q('id_DeskVO').checked = true; }
            // ###BEGIN###{DesktopType}
            QE('id_DeskType', false);
            // ###END###{DesktopType}
            // ###END###{Desktop}

            // ###BEGIN###{Desktop-Multi}
            desktopScreenInfo = null;
            // ###END###{Desktop-Multi}

            // Start pulling Intel AMT information
            amtstack.BatchEnum('', ['CIM_SoftwareIdentity', '*AMT_SetupAndConfigurationService'], processSystemVersion); // Get Intel AMT version information and plenty more
            //amtstack.Enum('CIM_LogicalElement', processSystemVersion); // Get Intel AMT version information and plenty more

            // ###BEGIN###{VersionWarning}
            QV('id_versionWarning', false);
            // ###END###{VersionWarning}

            // ###BEGIN###{Scripting-Editor}
            fupdatescript();
            // ###END###{Scripting-Editor}
        }

        function disconnect() {
            // ###BEGIN###{Desktop-Multi}
            if (desktopPollTimer != null) {clearInterval(desktopPollTimer); desktopPollTimer = null; }
            // ###END###{Desktop-Multi}

            // ###BEGIN###{Mode-NodeWebkit}
            if (urlvars['host']) {
                require('nw.gui').Window.get().close();
                //require('nw.gui').App.quit();
                return;
            }
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{Desktop}
            if (fullscreen) deskToggleFull();
            // ###END###{Desktop}

            // ###BEGIN###{IDER}
            iderStop();
            // ###END###{IDER}

            // ###BEGIN###{PowerControl}
            // ###BEGIN###{!Mode-MeshCentral2}
            if (amtPowerPollTimer != null) { clearInterval(amtPowerPollTimer); amtPowerPollTimer = null; }
            // ###END###{!Mode-MeshCentral2}
            // ###END###{PowerControl}

            // ###BEGIN###{SystemDefense}
            StopDefenseStatsTimer();
            // ###END###{SystemDefense}

            // ###BEGIN###{Scripting}
            script_Stop();
            // ###END###{Scripting}
            // ###BEGIN###{Scripting-Editor}
            breakScriptButton();
            // ###END###{Scripting-Editor}

            dialogclose(0);
            // ###BEGIN###{!Mode-MeshCentral2}
            QH('id_computername', '');
            // ###END###{!Mode-MeshCentral2}
            if (amtstack) {
                amtstack.onProcessChanged = null; // Un-hook progress indicator
                amtstack.CancelAllQueries(999); // Fail all pending WSMAN calls. Set to 999 to indicate not to call back any of the pending calls with errors.
                amtstack = null;
            }
            cleanup();
            wsstack = null;
            delete amtstack;
            onProcessChanged(0, 1);
            go(101);
            // ###BEGIN###{!Mode-MeshCentral2}

            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                QH('id_computername', format("Console de gestion à distance v{0}, serveur: {1}", version, meshCentralServer.host));
            } else {
                QH('id_computername', format("Console de gestion à distance v{0}", version));
            }
            // ###END###{MeshServerConnect}
            // ###BEGIN###{!MeshServerConnect}
            QH('id_computername', format("Console de gestion à distance v{0}", version));
            // ###END###{!MeshServerConnect}
            
            // ###END###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-NodeWebkit}
            require('nw.gui').Window.get().title = NW_WindowTitle;
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{Mode-MeshCentral2}
            Q('xconnectbutton1').value = "Relier";
            QH('id_messageviewstr', "Débranché");
            go(100);
            // ###END###{Mode-MeshCentral2}
        }

        function onProcessChanged(a, b) {
            QS('id_progressbar').width = ((a * 100) / b) + '%';
            if (a == 0) refreshButtons(true); // If nothing is being done, re-enable refresh buttons

            // ###BEGIN###{Mode-NodeWebkit}
            // Don't do any WSMAN if we don't need to do it.
            if ((urlvars['kvmonly'] == 1) || (fullscreenonly == true)) return;
            // ###END###{Mode-NodeWebkit}

            // If there is nothing being done now, see if we can pull more information
            if (a != 0 || !amtstack) return;
            if ((amtversion > 0) && ((amtFirstPull & 64) == 0)) {
                amtFirstPull |= 64;
                PullPowerPolicy();
                // ###BEGIN###{EventSubscriptions}
                subscriptionsFilters = null;
                PullEventSubscriptions();
                // ###END###{EventSubscriptions}
                // ###BEGIN###{AgentPresence}
                PullWatchdog();
                // ###END###{AgentPresence}

                // ###BEGIN###{Scripting-Editor}
                scriptViewButton(script_BuildingBlocks?1:0);
                // ###END###{Scripting-Editor}

                if (amtversion > 5) {
                    // ###BEGIN###{Certificates}
                    PullCertificates();
                    // ###END###{Certificates}
                    // ###BEGIN###{RemoteAccess}
                    PullRemoteAccess();
                    // ###END###{RemoteAccess}
                }
                return;
            }
            // ###BEGIN###{HardwareInfo}
            if ((amtFirstPull & 1) == 0) { PullHardware(); return; }
            // ###END###{HardwareInfo}
            // ###BEGIN###{EventLog}
            if ((amtFirstPull & 16) == 0) { PullEventLog(); return; }
            // ###END###{EventLog}
            // ###BEGIN###{AuditLog}
            if ((amtFirstPull & 32) == 0) { PullAuditLog(); return; }
            // ###END###{AuditLog}
        }

// ###BEGIN###{Mode-LMS}
        function toolmenuclick(x) {
            QV('id_menuitem1', currentView == 101);
            // ###BEGIN###{USBSetup}
            QV('id_menuitem2', currentView == 102);
            // ###END###{USBSetup}
            // ###BEGIN###{CertificateManager}
            QV('id_menuitem3', currentView == 103);
            // ###END###{CertificateManager}
            // ###BEGIN###{SessionRecording}
            QV('id_menuitem4', currentView == 104);
            // ###END###{SessionRecording}

            var d = (QS('id_computerSelectorMenu').display == 'none');
            if (d == true && xxdialogMode) return;
            xxdialogMode = (d == true)?999:undefined;
            QV('id_computerSelectorMenu', d);
            if (x == 0) return;
            go(x);
        }
// ###END###{Mode-LMS}

// ###BEGIN###{ComputerSelector}

        var computerlist = [];
        var currentcomputer = null;
        var computersRunningScripts = 0;

        function toolmenuclick(x) {
            QV('id_menuitem1', currentView == 101);
            // ###BEGIN###{USBSetup}
            QV('id_menuitem2', currentView == 102);
            // ###END###{USBSetup}
            // ###BEGIN###{CertificateManager}
            QV('id_menuitem3', currentView == 103);
            // ###END###{CertificateManager}
            // ###BEGIN###{SessionRecording}
            QV('id_menuitem4', currentView == 104);
            // ###END###{SessionRecording}

            var d = (QS('id_computerSelectorMenu').display == 'none');
            if (x == -1) { QV('id_computerSelectorMenu', false); xxdialogMode = undefined; return; }
            if (d == true && xxdialogMode) return;
            xxdialogMode = (d == true)?999:undefined;
            QV('id_computerSelectorMenu', d);
            if (x <= 0) return;
            go(x);
        }

        function computerFilterFunc() {
            var filter = computerFilter.value.toLowerCase();
            for (var w in computerlist) { QV('CX-' + computerlist[w].h, filter == '' || computerlist[w].checked == true || computerlist[w]['host'].toLowerCase().indexOf(filter) >= 0 || computerlist[w]['name'].toLowerCase().indexOf(filter) >= 0); }
        }

        // ###BEGIN###{ComputerSelector-Local}
        function addComputer() {
            if (xxdialogMode) return;

            // Build the list of groups
            var groups = [], x = '';
            for (var y in computerlist) { var computer = computerlist[y]; if ((computer.tags != null) && (computer.tags != '') && (groups.indexOf(computer.tags) == -1) && (computer.tags.indexOf('"') == -1)) { groups.push(computer.tags); } }
            groups.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
            for (var y in groups) { x += '<option value="' + groups[y] + '">'; }
            QH('d4devGroups', x);

            // Display the dialog box
            d4name.value = d4tags.value = d4hostname.value = d4password.value = '';
            d4username.value = "administrateur";
            if (kerberos != null) {
                QH('d4security', '<option value=0>' + "Digeste / Aucun" + '</option><option value=1>' + "Digest / TLS" + '</option><option value=2>' + "Kerberos / Aucun" + '</option><option value=3>' + "Kerberos / TLS" + '</option>');
            } else {
                QH('d4security', '<option value=0>' + "Digeste / Aucun" + '</option><option value=1>' + "Digest / TLS" + '</option>');
            }
            d4security.value = 0;
            setDialogMode(4, "Ajouter un ordinateur", 3, function () { addComputerButton(); });
            updateComputerDialog();
            d4name.focus();
        }

        // Toggle the select of all computers
        // TODO: Fix problem with this combined with filter box
        function selectAllComputers() {
            var x = false;
            for (var y in computerlist) { if (computerlist[y].checked == false) { x = true; } }
            for (var y in computerlist) { computerlist[y].checked = x; Q('SJ-' + computerlist[y]['h']).checked = x; } // TODO: Only select or un-select when element is visible
        }

        function deleteComputers() {
            if (xxdialogMode) return;
            // Figure out how many computers are selected.
            var clist = [];
            for (var y in computerlist) { if (computerlist[y].checked == true) { clist.push(computerlist[y]); } }
            if (clist.length == 0) { clist.push(currentcomputer); }
            if (clist.length == 1) {
                setDialogMode(11, "Supprimer des ordinateurs", 3, deleteComputersEx, '<br>' + "Supprimer l'ordinateur?", clist);
            } else {
                setDialogMode(11, "Supprimer des ordinateurs", 3, deleteComputersEx, '<br>' + format("Supprimer {0} ordinateurs?", clist.length), clist);
            }
        }

        function deleteComputersEx(button, clist) {
            for (var i in clist) {
                var handleToDelete = clist[i]['h'];
                if ((currentcomputer != null) && (currentcomputer['h'] == handleToDelete)) { currentcomputer = null; }
                for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == handleToDelete) { computerlist.splice(x, 1); } }
            }
            saveComputers();
            updateComputerList();
            updateComputerDetails();
        }

        function newComputerList() {
            if (xxdialogMode) return;
            QH('id_dialogMessage', "Clear list of known Intel&reg; AMT computers?");
            setDialogMode(1, "Nouvelle liste d'ordinateurs", 3, newComputerListOk);
        }

        function newComputerListOk(r) {
            computerlist = [];
            currentcomputer = null;
            // ###BEGIN###{!Mode-NodeWebkit}
            idx_d18computerfilename.value = 'computerlist.json';
            // ###END###{!Mode-NodeWebkit}
            saveComputers();
            updateComputerList();
        }
        
        function openComputerList() {
            if (xxdialogMode) return;
            // ###BEGIN###{!Mode-NodeWebkit}
            setDialogMode(17, "Open Computer List", 3, openComputerListOk);
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = Q('idx_d17computerlistfile');
            if (chooser.getAttribute('eventset') != 1) {
                chooser.setAttribute('eventset', '1');
                chooser.addEventListener('change', NW_LoadComputersEx, false);
            }
            chooser.value = null;
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }

        function openComputerListOk(r) {
            if (r != 1) return;
            var x = Q('idx_d17computerlistfile');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = function(file) { onComputerListRead(file, Q('idx_d17computerlistfile').files[0].name); }
            reader.readAsBinaryString(x.files[0]);
        }
        
        function onComputerListRead(file, name, pass) {
            var x;
            if (name.toLowerCase().endsWith('.csv')) {
                // Load from a CSV file
                x = { computers: [] };
                var lines = file.target.result.split('\r\n').join('\n').split('\n'), headers = {}, count = 0;
                for (var i in lines) {
                    var values = lines[i].split(',');
                    if (i == 0) {
                        // Fill the headers
                        for (var j in values) {
                            if (values[j] == 'Intel AMT FQDN') { headers[j] = 'name'; }
                            if (values[j] == 'Intel AMT IPv4') { headers[j] = 'host'; }
                            if (values[j] == 'Intel AMT Version') { headers[j] = 'ver'; }
                            //if (values[j] == 'Last Connection Time') { headers[j] = 'date'; }
                        }
                    } else {
                        // Fill data
                        var computerEntry = {};
                        for (var j in values) {
                            if (headers[j] && (values[j].length > 0)) { computerEntry[headers[j]] = values[j]; }
                        }
                        if (computerEntry.host || computerEntry.name) {
                            if (computerEntry.host == null) { computerEntry.host = computerEntry.name; }
                            if (computerEntry.user == null) { computerEntry.user = 'admin'; }
                            if (computerEntry.pass == null) { computerEntry.pass = ''; }
                            if (computerEntry.tls == null) { computerEntry.tls = 1; }
                            x.computers.push(computerEntry);
                            count++;
                        }
                    }
                }
                if (count == 0) { x = {}; }
            } else {
                try { x = JSON.parse(file.target.result); } catch (ex) { }
                // ###BEGIN###{Mode-NodeWebkit}
                if (x && x['magic'] == '3209ruwpcoinaT4r9w347t0e4ug') {
                    if (pass) {
                        // Decrypt the file
                        x = getDecryptedData(x, pass);
                        if (x && (x != null)) { x = JSON.parse(x); }
                    } else {
                        // Prompt to the password
                        var x = "Le fichier sélectionné nécessite un mot de passe." + '<br/><br/><div style=height:26px><input id=idx_filepass type=password style=float:right;width:200px onkeyup=filePasswordDialogUpdate()><div>' + "Mot de passe" + '</div></div>';
                        setDialogMode(11, "Mot de passe du fichier", 3, onComputerListReadEx, x, [file, name]);
                        filePasswordDialogUpdate();
                        return;
                    }
                }
                // ###END###{Mode-NodeWebkit}
            }
            if (!x || !x['computers']) {
                messagebox("Fichier ouvert", "Fichier de liste d'ordinateurs invalide ou corrompu. Incapable d'ouvrir.");
            } else {
                // ###BEGIN###{!Mode-NodeWebkit}
                idx_d18computerfilename.value = name;
                // ###END###{!Mode-NodeWebkit}
                currentcomputer = null;
                computerlist = x['computers'];
                for (var i in computerlist) { computerlist[i]['h'] = Math.random(); computerlist[i].checked = false; }
                updateComputerList();
                saveComputers();
            }
        }

        function onComputerListReadEx(button, tag) { onComputerListRead(tag[0], tag[1], Q('idx_filepass').value); }
        function filePasswordDialogUpdate() { QE('idx_dlgOkButton', passwordcheck(Q('idx_filepass').value)); }

        // ###BEGIN###{FileSaver}

        function saveComputerListUpdate() {
            var ok = true;
            // ###BEGIN###{Mode-NodeWebkit}
            QV('d18showpassword', d18usepassword.checked);
            if (d18usepassword.checked == true) { ok = (passwordcheck(d18password1.value) && (d18password1.value == d18password2.value)) };
            // ###END###{Mode-NodeWebkit}
            QE('idx_dlgOkButton', ok);
        }

        function saveComputerList() {
            if (xxdialogMode) return;
            // ###BEGIN###{Mode-NodeWebkit}
            d18usepassword.checked = false;
            d18password1.value = '';
            d18password2.value = '';
            // ###END###{Mode-NodeWebkit}
            setDialogMode(18, "Enregistrer la liste des ordinateurs", 3, saveComputerListOk);
            saveComputerListUpdate();
        }

        function saveComputerListOk() {
            var computerlist2 = Clone(computerlist);
            for (var i in computerlist2) { delete computerlist2[i]['h']; delete computerlist2[i].checked; delete computerlist2[i]['consolemsg']; }
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(JSON.stringify({ 'webappversion':version, 'computers':computerlist2 }, null, '  ').replace(/\n/g, '\r\n')), idx_d18computerfilename.value);
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', 'computerlist.json');
            chooser.addEventListener('change', function() {
                if (this.value == '') return;
                if (d18usepassword.checked == false) { 
                    require('fs').writeFile(this.value, JSON.stringify({ 'webappversion': version, 'computers': computerlist2 }, null, '  ').replace(/\n/g, '\r\n'), function () { });
                } else {
                    require('fs').writeFile(this.value, JSON.stringify(getEncryptedData(JSON.stringify({ 'webappversion': version, 'computers': computerlist2 }, null, '  '), d18password1.value), null, '  ').replace(/\n/g, '\r\n'), function () { });
                }
                this.value = '';
            }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }

        function getEncryptedData(dataStr, password) {
            var crypto = require('crypto');
            var salt = crypto.randomBytes(16);
            var key = crypto.pbkdf2Sync(password, salt, 128000, 16, 'sha512');
            var iv = Math.round((Math.pow(36, 13) - Math.random() * Math.pow(36, 12))).toString(36).slice(1);
            var cipher = crypto.createCipheriv('aes-256-gcm', key.toString('hex'), iv);
            var encrypted = cipher.update(dataStr, 'utf8', 'hex') + cipher.final('hex');
            return { 'magic': '3209ruwpcoinaT4r9w347t0e4ug', 'version': 1, 'salt': salt.toString('hex'), 'iv': iv, 'tag': cipher.getAuthTag().toString('hex'), 'data': encrypted };
        }

        function getDecryptedData(encryptedData, password) {
            var crypto = require('crypto');
            var salt = new require('buffer').Buffer(encryptedData['salt'], 'hex');
            var iv = encryptedData['iv'];
            var tag = new require('buffer').Buffer(encryptedData['tag'], 'hex');
            var data = encryptedData['data'];
            var key = crypto.pbkdf2Sync(password, salt, 128000, 16, 'sha512');
            var decipher = crypto.createDecipheriv('aes-256-gcm', key.toString('hex'), iv);
            decipher.setAuthTag(tag);
            var decrypted = decipher.update(data, 'hex', 'utf8') + decipher.final('utf8');
            return decrypted;
        }

        // ###END###{FileSaver}

        function updateComputerDialog() {
            var k = Q('d4security').value >= 2;
            QV('d4digest', !k);
            QV('d4kerb', k);
            var hostSplit = d4hostname.value.split(':');
            var hostnameok = (d4hostname.value.length > 0) && (hostSplit.length < 3);
            if (hostnameok && (hostSplit.length == 2)) { var hostport = parseInt(hostSplit[1]); hostnameok = (hostport > 0) && (hostport < 65536) && (hostport == hostSplit[1]); }
            QS('d4hostname')['background-color'] = (hostnameok ? 'white' : 'LightYellow');
            if (k && hostnameok) {
                QE('idx_dlgOkButton', d4hostname.value.length > 0);
            } else {
                QS('d4username')['background-color'] = (((d4username.value.length > 0) && (d4username.value != '*')) ? 'white' : 'LightYellow');
                QS('d4password')['background-color'] = (((d4username.value == '$$OsAdmin') || passwordcheck(d4password.value) || d4password.value == '') ? 'white' : 'LightYellow');
                QE('idx_dlgOkButton', d4hostname.value.length > 0 && d4username.value.length > 0 && d4username.value != '*' && ((d4username.value == '$$OsAdmin') || passwordcheck(d4password.value) || d4password.value == ''));
            }
        }

        function addComputerButton() {
            var k = Q('d4security').value >= 2;
            // ###BEGIN###{!Mode-NodeWebkit}
            if (k) {
                computerlist.push({ 'h': Math.random(), 'name': encodeURIComponent(d4name.value), 'host': encodeURIComponent(d4hostname.value), 'tags': encodeURIComponent(d4tags.value), 'user': '*', 'pass': encodeURIComponent(Q('d4kerberos').value), 'tls': d4security.value % 2 });
            } else {
                computerlist.push({ 'h': Math.random(), 'name': encodeURIComponent(d4name.value), 'host': encodeURIComponent(d4hostname.value), 'tags': encodeURIComponent(d4tags.value), 'user': encodeURIComponent(d4username.value), 'pass': encodeURIComponent(d4password.value), 'tls': d4security.value % 2 });
            }
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            if (k) {
                computerlist.push({ 'h': Math.random(), 'name': encodeURIComponent(d4name.value), 'host': encodeURIComponent(d4hostname.value), 'tags': encodeURIComponent(d4tags.value), 'user': '*', 'pass': encodeURIComponent(Q('d4kerberos').value), 'tls': d4security.value % 2, 'tlscerthash': getCertPinning(d4hostname.value) });
            } else {
                computerlist.push({ 'h': Math.random(), 'name': encodeURIComponent(d4name.value), 'host': encodeURIComponent(d4hostname.value), 'tags': encodeURIComponent(d4tags.value), 'user': encodeURIComponent(d4username.value), 'pass': encodeURIComponent(d4password.value), 'tls': d4security.value % 2, 'tlscerthash': getCertPinning(d4hostname.value) });
            }
            // ###END###{Mode-NodeWebkit}
            saveComputers();
            updateComputerList();
        }

        function computerSelector_FileSelectHandler(e) {
            haltEvent(e);
            if (e.dataTransfer == null || e.dataTransfer.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = function(file) { onComputerListRead(file, e.dataTransfer.files[0].name); }
            reader.readAsText(e.dataTransfer.files[0]);
        }

        function computerEdit(h) {
            if (xxdialogMode) return;
            var c = null;
            for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }

            // Build the list of groups
            var groups = [], x = '';
            for (var y in computerlist) { var computer = computerlist[y]; if ((computer.tags != null) && (computer.tags != '') && (groups.indexOf(computer.tags) == -1) && (computer.tags.indexOf('"') == -1)) { groups.push(computer.tags); } }
            groups.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
            for (var y in groups) { x += '<option value="' + groups[y] + '">'; }
            QH('d4devGroups', x);

            // If connected to a MeshCentral server, only edit the device name
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                var x = '<div style=height:26px><input id=d11deviceName style=float:right;width:200px value="' + decodeURIComponent(c['name'] ? c['name'] : '') + '"><div>' + "Nom familier" + '</div></div>';
                setDialogMode(11, "Modifier l'appareil", 3, computerEditMeshOk, x, c);
                return;
            }
            // ###END###{MeshServerConnect}

            if (kerberos != null || c['user'] == '*') {
                QH('d4security', '<option value=0>' + "Digeste / Aucun" + '</option><option value=1>' + "Digest / TLS" + '</option><option value=2>' + "Kerberos / Aucun" + '</option><option value=3>' + "Kerberos / TLS" + '</option>');
            } else {
                QH('d4security', '<option value=0>' + "Digeste / Aucun" + '</option><option value=1>' + "Digest / TLS" + '</option>');
            }
            d4name.value = decodeURIComponent(c['name']?c['name']:'');
            d4tags.value = decodeURIComponent(c['tags']?c['tags']:'');
            d4hostname.value = decodeURIComponent(c['host']);
            d4security.value = c['tls'] + ((c['user'] == '*')?2:0);
            if (c['user'] == '*') {
                d4kerberos.value = decodeURIComponent(c['pass']?c['pass']:'');
            } else {
                d4username.value = decodeURIComponent(c['user']?c['user']:'');
                d4password.value = decodeURIComponent(c['pass']?c['pass']:'');
            }
            setDialogMode(4, "Modifier l'appareil", 7, function (r) { computerEditOk(r, h); });
            updateComputerDialog();
            Q('d4name').focus();
        }

        // ###BEGIN###{MeshServerConnect}
        function computerEditMeshOk(button, c) {
            if (Q('d11deviceName').value != c.name) { meshCentralServer.send({ action: 'changedevice', nodeid: c._id, name: Q('d11deviceName').value }); }
        }
        // ###END###{MeshServerConnect}

        function computerEditOk(r, h) {
            if (r == 2) { computerRemoveEx(h); return; }
            var c = null;
            for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }
            c['name'] = decodeURIComponent(d4name.value);
            c['tags'] = decodeURIComponent(d4tags.value);
            c['host'] = decodeURIComponent(d4hostname.value);
            if (d4security.value < 2) {
                // Digest authentication
                c['user'] = decodeURIComponent(d4username.value);
                c['pass'] = decodeURIComponent(d4password.value);
            } else {
                // Kerberos authentication
                c['user'] = '*';
                c['pass'] = decodeURIComponent(d4kerberos.value);
            }
            c['tls'] = d4security.value % 2;

            //for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { computerlist.splice(x, 1); } }
            //var c = { 'h': h, "name": d4name.value, "host": d4hostname.value, "user": d4username.value, "pass": d4password.value, "tls": d4security.value };
            //computerlist.push(c);
            //if (currentcomputer['h'] == c['h']) { currentcomputer = c; }
            saveComputers();
            //computerSelect();
            updateComputerList();
            updateComputerDetails();
        }

        function computerRemoveEx(h) {
            if (currentcomputer['h'] == h) currentcomputer = null;
            for (x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { computerlist.splice(x, 1); } }
            saveComputers();
            updateComputerList();
            updateComputerDetails();
        }

        function onFilterFocus(x) { filterFocus = x; }

        // ###END###{ComputerSelector-Local}

        function updateComputerList() {
            QH('id_computerList', '');
            // ###BEGIN###{MeshServerConnect}
            if ((meshCentralServer != null) && (computerlist.length == 0)) {
                QV('id_noKnownComputers', false);
                if (meshCentralServer.socketState < 3) {
                    QH('id_computerList', '<div style=width:99%;text-align:center;margin-top:36px;color:gray>' + "De liaison..." + '</div>');
                } else {
                    QH('id_computerList', '<div style=width:99%;text-align:center;margin-top:36px;color:gray>' + "Aucun ordinateur Intel&reg; AMT trouvé sur ce compte." + '</div>');
                }
                QV('id_noKnownComputers', false);
            } else {
                QV('id_noKnownComputers', computerlist.length == 0);
            }
            // ###END###{MeshServerConnect}
            // ###BEGIN###{!MeshServerConnect}
            QV('id_noKnownComputers', computerlist.length == 0);
            // ###END###{!MeshServerConnect}
            QV('computerFilter', computerlist.length != 0);
            // ###BEGIN###{FileSaver}
            QE('saveComputersButton', computerlist.length != 0);
            // ###END###{FileSaver}
            // ###BEGIN###{Scripting}
            computersRunningScripts = 0;
            var computersWithScriptsMsgs = 0;
            
            for (var y in computerlist) { if (computerlist[y].scriptstate) computersRunningScripts++; if (computerlist[y]['consolemsgs']) computersWithScriptsMsgs++; }
            // ###BEGIN###{Mode-NodeWebkit}
            if (urlvars['autoexit'] && computersRunningScripts == 0 && computersWithScriptsMsgs > 0) {
                require('nw.gui').Window.get().close();
                //require('nw.gui').App.quit();
                return;
            } // Exit if no scripts are running
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{ComputerSelectorToolbar}
            QE('idx_runScriptOnComputersButton', computerlist.length != 0);
            // ###BEGIN###{MeshServerConnect}
            QV('id_noScriptButtons', (computersRunningScripts == 0) && (meshCentralServer == null));
            QV('idx_disconnectMeshCentralButton', meshCentralServer != null);
            QV('idx_runScriptOnComputersButton', meshCentralServer == null);
            QV('toolmenuicondiv', meshCentralServer == null);
            // ###BEGIN###{Mode-NodeWebkit}
            QV('LeftMenuMyCerts', meshCentralServer == null);
            QV('LeftMenuMyUsb', meshCentralServer == null);
            QV('LeftMenuPlayer', meshCentralServer == null);
            // ###END###{Mode-NodeWebkit}
            // ###END###{MeshServerConnect}
            // ###BEGIN###{!MeshServerConnect}
            QV('id_noScriptButtons', computersRunningScripts == 0);
            // ###END###{!MeshServerConnect}
            idx_runScriptOnComputersButton.value = (computersRunningScripts > 0 ? "Arrêter tous les scripts" : "Script de lancement...")
            // ###END###{ComputerSelectorToolbar}
            // ###END###{Scripting}
            QV('id_computerDetailsParent', computerlist.length != 0);
            QS('id_computerListParent').right = (computerlist.length == 0 ? 0 : '300px');
            computerlist.sort(function (a, b) { var aa = a['name'] ? a['name'].toLowerCase() : a['host'].toLowerCase(); var bb = b['name'] ? b['name'].toLowerCase() : b['host'].toLowerCase(); if (aa > bb) { return 1; } if (aa < bb) { return -1; } return 0; });
            if (currentcomputer == null && computerlist.length > 0) { currentcomputer = computerlist[0]; }

            // Built a sorted list of groups
            var groups = [''], groupHtml = {};
            for (var y in computerlist) { var computer = computerlist[y]; if ((computer.tags != null) && (groups.indexOf(computer.tags) == -1)) { groups.push(computer.tags); } }
            groups.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
            for (var y in groups) { groupHtml[groups[y]] = ''; }

            // Go thru each computer and create the HTML entry
            for (var y in computerlist) {
                var computer = computerlist[y], extra = [], group = '', disabled = false;
                if (computer.tags != null) { group = computer.tags; }
                if (computer['user'] == '*') { extra.push("Kerberos"); } else { if (computer['user']) { extra.push(EscapeHtml(decodeURIComponent(computer['user']))); } }
                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) {
                    var securityok = false;
                    if (computer['conn']) {
                        if ((computer['conn'] & 2) != 0) { extra.push("CIRA"); securityok = true; } else {
                            if ((computer['conn'] & 4) != 0) { extra.push("Direct"); }
                            else if ((computer['conn'] & 8) != 0) { extra.push("Relais"); }
                        }
                    }
                    if (securityok == true) {
                        if (computer['tls'] != 0) { extra.push("TLS"); }
                    } else {
                        extra.push((computer['tls'] == 0) ? NoBreak("Pas de sécurité") : "TLS");
                    }
                } else {
                    extra.push((computer['tls'] == 0) ? NoBreak("Pas de sécurité") : "TLS");
                }
                // ###END###{MeshServerConnect}
                // ###BEGIN###{!MeshServerConnect}
                extra.push((computer['tls'] == 0) ? NoBreak("Pas de sécurité") : "TLS");
                // ###END###{!MeshServerConnect}
                var name = decodeURIComponent(computer['host']);
                if (computer['name'] && computer['name'] != '') name = decodeURIComponent(computer['name']);

                var x = '<div id=CX-' + computer['h'] + ' ondblclick=computerEdit(' + computer['h'] + ')>';
                // ###BEGIN###{Look-Commander}
                // ###BEGIN###{ComputerSelectorScanner}
                var gray = false;
                if (NW_AmtScanMenuItem && (NW_AmtScanMenuItem.checked == true)) { gray = ((!globalAmtScanner.scanTable[computer['h']]) || (globalAmtScanner.scanTable[computer['h']].scanstate != 1)); }
                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) { disabled = gray = ((computer.conn & 14) == 0); }
                // ###END###{MeshServerConnect}
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div id=SI-' + computer['h'] + ' class=\"j' + (computer['icon'] ? computer['icon'] : 1) + (gray ? ' gray' : '') + '\" style=float:left;margin-left:4px;margin-right:4px></div>';
                // ###END###{!ComputerSelectorNoImages}
                // ###END###{ComputerSelectorScanner}
                // ###BEGIN###{!ComputerSelectorScanner}
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div id=SI-' + computer['h'] + ' class=\"j' + (computer['icon'] ? computer['icon'] : 1) + '\" style=float:left;margin-left:4px;margin-right:4px></div>';
                // ###END###{!ComputerSelectorNoImages}
                // ###END###{!ComputerSelectorScanner}
                // ###END###{Look-Commander}

                // ###BEGIN###{ComputerSelectorNoImages}
                x += '<div><table style="height:24px;width:calc(100%);margin:3px;cursor:pointer;border:none" cellspacing=0 cellpadding=0';
                // ###END###{ComputerSelectorNoImages}
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div><table style="height:24px;width:calc(100% - 38px);margin:3px;cursor:pointer;border:none" cellspacing=0 cellpadding=0';
                // ###END###{!ComputerSelectorNoImages}

                // ###BEGIN###{ComputerSelector-Local}
                // ###BEGIN###{ContextMenus}
                var cmenus = [];
                // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                if ((computer.scriptstate == undefined) && (disabled == false)) {
                    cmenus.push("Relier" + '#computerConnect(event,' + computer['h'] + ')');
                    cmenus.push("Windowed Connect" + '#computerConnect(event,' + computer['h'] + ',100)');
                    cmenus.push('-');
                    cmenus.push("Bureau" + '#computerConnect(event,' + computer['h'] + ',1)');
                    cmenus.push("Bureau uniquement" + '#computerConnect(event,' + computer['h'] + ',3)');
                    cmenus.push("Terminal" + '#computerConnect(event,' + computer['h'] + ',4)');
                }
                // ###END###{!ComputerSelector-Local-ScriptOnly}
                // ###BEGIN###{Scripting}
                if (computer.scriptstate != null) cmenus.push("Arrêter le script" + '#computerStopScript(event,' + computer['h'] + ')');
                if (computer['consolemsgs'] != null) cmenus.push("Sortie de script ..." + '#mscript_showComputerScriptOutput(' + computer['h'] + ')');
                // ###END###{Scripting}
                if (computer.scriptstate == null) cmenus.push("Éditer..." + '#computerEdit(' + computer['h'] + ')');
                x += ' cm=\'' + cmenus.join('|') + '\'';
                // ###END###{ContextMenus}
                // ###END###{ComputerSelector-Local}
                x += ' onclick="computerSelect(event, ' + computer['h'] + ')" id=CI-' + computer['h'] + '>';
                x += '<td id=LCX-' + computer['h'] + ' class=g1 style=float:none>&nbsp;</td>' // Left side gray scale

                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer == null) {
                // ###END###{MeshServerConnect}
                // ###BEGIN###{ComputerSelectorScanner}
                if (NW_AmtScanMenuItem && (NW_AmtScanMenuItem.checked == true)) {
                    var scanstate = globalAmtScanner.scanTable[computer['h']], scancolor = '';
                    if (scanstate) { if (scanstate.scanstate == 1) scancolor = ';background-color:green'; if (scanstate.scanstate == 0) scancolor = ';background-color:red'; }
                    x += '<td style=width:12px title="' + "Réponse Intel&reg; AMT RMCP" + '"><div id=SS-' + computer['h'] + ' class=computeritemcir style=' + scancolor + '></div>';
                }
                // ###END###{ComputerSelectorScanner}
                // ###BEGIN###{MeshServerConnect}
                }
                // ###END###{MeshServerConnect}

                // ###BEGIN###{Look-ISDU}
                x += '<td style=width:24px><img src=images-isdu/ComputerIcon.png style=padding-top:2px /></td>';
                // ###END###{Look-ISDU}
                // ###BEGIN###{Look-Commander}
                //x += '<td class=j' + (computer['icon'] ? computer['icon'] : 1) + '></td>';
                // ###END###{Look-Commander}
                // ###BEGIN###{Look-BrandedCommander}
                x += '<td><img src=images-BrandedCommander/ComputerIcon.png style=vertical-align:text-top /></td>';
                // ###END###{Look-BrandedCommander}
                // ###BEGIN###{Scripting}
                x += '<td style=width:10px><input id=SJ-' + computer['h'] + ' type=checkbox onclick=onComputerChecked()' + (computer.checked?' checked':'') + (computersRunningScripts>0?' disabled':'') + ' /></td>';
                // ###END###{Scripting}

                x += '<td align=left><b style=font-size:16px>' + EscapeHtml(name) + '</b></td>';

                // ###BEGIN###{!Scripting}
                // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
                x += '<td align=right style=padding-right:5px>' + extra.join(', ') + '</td>';
                // ###END###{ComputerSelector-Local-ScriptOnly}
                // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                x += '<td align=right style=padding-right:5px>' + extra.join(', ') + '</td><td style=width:1px;padding-right:5px>' + AddButton2("Relier", 'computerConnect(event,' + computer['h'] + ')', disabled ? 'disabled=disabled' : '') + '</td>';
                // ###END###{!ComputerSelector-Local-ScriptOnly}
                // ###END###{!Scripting}
                // ###BEGIN###{Scripting}
                if (computersRunningScripts == 0) {
                    // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
                    x += '<td align=right style=padding-right:5px>' + extra.join(', ') + '</td>';
                    // ###END###{ComputerSelector-Local-ScriptOnly}
                    // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                    x += '<td align=right style=padding-right:5px>' + extra.join(', ') + '</td><td style=width:1px;padding-right:5px>' + AddButton2("Relier", 'computerConnect(event,' + computer['h'] + ')', disabled?'disabled=disabled':'') + '</td>';
                    // ###END###{!ComputerSelector-Local-ScriptOnly}
                } else {
                    if (computer.scriptstate) { x += '<td align=right style=padding-right:5px id=XI-' + computer['h'] + '>' + EscapeHtml(computer['consolemsg']) + '</td><td style=width:1px>' + AddButton2("Arrêtez", 'computerStopScript(event,' + computer['h'] + ')') + '</td>'; }
                }
                // ###END###{Scripting}

                x += '<td id=RCX-' + computer['h'] + ' class=g2 style=float:none>&nbsp;</td>' // Right side gray scale
                x += '</table></div></div>';

                groupHtml[group] += x; // Add this device to the proper group
            }

            // Append all the groups into the final HTML
            if (computerlist.length > 0) {
                var x = '';
                for (var y in groups) {
                    if (groups[y] != '') { x += '<div style="font-size:14px;border-bottom:1px solid lightgray;margin-left:4px;margin-top:6px"><b>' + EscapeHtml(groups[y]) + '</b></div>'; }
                    x += groupHtml[groups[y]];
                }
                QH('id_computerList', '<div style=width:99%>' + x + '</div>');
            }
            updateComputerDetails();
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
        }

        function onComputerChecked() {
            for (var y in computerlist) { computerlist[y].checked = Q('SJ-' + computerlist[y]['h']).checked; }
        }

        function addComputerDetailsEntry(x, y) {
            //return '<div class=log style=border-radius:4px;padding:3px;margin-bottom:3px><div style=width:100%;font-size:9px>' + x + '</div><div style=width:100%>&nbsp;' + y + '</div></div>';
            return '<div style=border-radius:4px;padding:3px;margin-bottom:3px;background-color:#ddd><div style=width:100%;font-size:9px>' + x + '</div><div style=width:100%>&nbsp;' + y + '</div></div>';
        }

        function updateComputerDetails() {
            var x = '<div style=position:absolute;top:0;right:0;left:0;bottom:0>', disabled = false;
            if (currentcomputer != null) {
                // ###BEGIN###{Look-Commander}
                // Put the big computer logo
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div style=position:absolute;top:4px;left:4px;right:4px;bottom:80px>';
                if (currentcomputer['name']) x += '<div style=width:100%;text-align:center><b>' + EscapeHtml(decodeURIComponent(currentcomputer['name'])) + '</b></div>';
                // ###BEGIN###{ComputerSelectorScanner}
                var icon = 1, gray = false;
                if ((NW_AmtScanMenuItem) && (NW_AmtScanMenuItem.checked == true)) { gray = (!globalAmtScanner.scanTable[currentcomputer['h']]) || (globalAmtScanner.scanTable[currentcomputer['h']].scanstate != 1); }
                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) { disabled = gray = ((currentcomputer.conn & 14) == 0); }
                // ###END###{MeshServerConnect}
                if (currentcomputer['icon']) { icon = parseInt(currentcomputer['icon']); }
                x += '<img ' + (gray ? 'class=gray ' : '') + 'src="images-commander/icons200-' + icon + '-1.png" onclick=showIconSelector() height=200 width=200 style=margin-left:50px;cursor:pointer></img>';
                // ###END###{ComputerSelectorScanner}
                // ###BEGIN###{!ComputerSelectorScanner}
                var icon = 1;
                if (currentcomputer['icon']) { icon = parseInt(currentcomputer['icon']); }
                x += '<img src="images-commander/icons200-' + icon + '-1.png" onclick=showIconSelector() height=200 width=200 style=margin-left:50px;cursor:pointer></img>';
                // ###END###{!ComputerSelectorScanner}
                // ###END###{!ComputerSelectorNoImages}

                x += '</div>';
                // ###END###{Look-Commander}

                var bottomButtons = '';
                var bottomButtonsHeight = 0;
                if (computersRunningScripts == 0) {
                    //bottomButtons += '<div style=position:fixed;bottom:8px;right:5px>';
                    bottomButtonsHeight = 14 + 20;
                    bottomButtons += '<div style=position:absolute;bottom:8px;left:4px;right:4px>';
                    // ###BEGIN###{Scripting}
                    if (currentcomputer['consolemsgs']) { bottomButtonsHeight += 20; bottomButtons += '<input type=Button value="' + "Afficher la sortie du script ..." + '" style=width:292px onclick=mscript_showComputerScriptOutput(' + currentcomputer['h'] + ')><br>'; }
                    // ###END###{Scripting}
                    // ###BEGIN###{ComputerSelector-Local}
                    // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                    bottomButtons += '<input type=Button value="' + "Éditer..." + '" style=width:146px onclick=computerEdit(' + currentcomputer['h'] + ')>';
                    bottomButtons += '<input type=Button value="' + "Relier" + '" style=width:146px onclick=computerConnect(event,' + currentcomputer['h'] + ') ' + (disabled ? 'disabled=disabled' : '') + '>';
                    // ###END###{!ComputerSelector-Local-ScriptOnly}
                    // ###BEGIN###{ComputerSelector-Local-ScriptOnly}
                    bottomButtons += '<input type=Button value="' + "Éditer..." + '" style=width:292px onclick=computerEdit(' + currentcomputer['h'] + ')>';
                    // ###END###{ComputerSelector-Local-ScriptOnly}
                    // ###END###{ComputerSelector-Local}
                    // ###BEGIN###{!ComputerSelector-Local}
                    // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                    bottomButtons += '<input type=Button value="' + "Relier" + '" style=width:292px onclick=computerConnect(event,' + currentcomputer['h'] + ' ' + (disabled ? 'disabled=disabled' : '') + ')>';
                    // ###END###{!ComputerSelector-Local-ScriptOnly}
                    // ###END###{!ComputerSelector-Local}
                    bottomButtons += '</div>';
                } else {
                    // ###BEGIN###{Scripting}
                    if (currentcomputer.scriptstate || currentcomputer['consolemsgs']) {
                        //bottomButtons += '<div style=position:fixed;bottom:8px;right:5px>';
                        bottomButtonsHeight = 14;
                        bottomButtons += '<div style=position:absolute;bottom:8px;left:4px;right:4px>';
                        if (currentcomputer['consolemsgs'] != null) { bottomButtonsHeight += 20; bottomButtons += '<input type=Button value="' + "Afficher la sortie du script ..." + '" style=width:292px onclick=mscript_showComputerScriptOutput(' + currentcomputer['h'] + ')><br>'; }
                        if (currentcomputer.scriptstate != null) { bottomButtonsHeight += 20; bottomButtons += '<input type=Button value="' + "Arrêter le script" + '" style=width:292px onclick=computerStopScript(event,' + currentcomputer['h'] + ')>'; }
                        bottomButtons += '</div>';
                    }
                    // ###END###{Scripting}
                }

                // ###BEGIN###{Look-Commander}
                // ###BEGIN###{!ComputerSelectorNoImages}
                x += '<div style="overflow-y:auto;position:absolute;top:216px;left:4px;right:4px;bottom:' + bottomButtonsHeight + 'px">';
                // ###END###{!ComputerSelectorNoImages}
                // ###BEGIN###{ComputerSelectorNoImages}
                x += '<div style="overflow-y:auto;position:absolute;top:4px;left:4px;right:4px;bottom:' + bottomButtonsHeight + 'px">';
                // ###END###{ComputerSelectorNoImages}
                // ###END###{Look-Commander}
                // ###BEGIN###{!Look-Commander}
                x += '<div style="overflow-y:auto;position:absolute;top:4px;left:4px;right:4px;bottom:' + bottomButtonsHeight + 'px">';
                if (currentcomputer['name']) x += addComputerDetailsEntry("Nom familier", EscapeHtml(decodeURIComponent(currentcomputer['name'])));
                // ###END###{!Look-Commander}
                x += addComputerDetailsEntry("Nom d'hôte", decodeURIComponent(currentcomputer['host']));

                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer == null) {
                // ###END###{MeshServerConnect}
                if (currentcomputer['user'] != '*') {
                    x += addComputerDetailsEntry("Authentification", "Digeste /" + EscapeHtml(decodeURIComponent(currentcomputer['user'])));
                } else {
                    if (currentcomputer['pass'] == '') {
                        x += addComputerDetailsEntry("Authentification", "Kerberos");
                    } else {
                        x += addComputerDetailsEntry("Authentification", "Kerberos /" + EscapeHtml(decodeURIComponent(currentcomputer['pass'])));
                    }
                }
                x += addComputerDetailsEntry("Sécurité", ((currentcomputer['tls'] == 0)?"Aucun":"Sécurité TLS"));
                if (currentcomputer['tags']) { x += addComputerDetailsEntry("Nom de groupe", EscapeHtml(decodeURIComponent(currentcomputer['tags']))); }
                // ###BEGIN###{MeshServerConnect}
                } else {
                    if (currentcomputer['tags']) { x += addComputerDetailsEntry("Groupe d'appareils", EscapeHtml(decodeURIComponent(currentcomputer['tags']))); }
                    if (currentcomputer['conn']) {
                        var cn = [];
                        if ((currentcomputer['conn'] & 1) != 0) cn.push('Agent');
                        if ((currentcomputer['conn'] & 2) != 0) cn.push('CIRA');
                        else if ((currentcomputer['conn'] & 4) != 0) cn.push('Direct');
                        else if ((currentcomputer['conn'] & 8) != 0) cn.push('Relay');
                        x += addComputerDetailsEntry("Connectivité", cn.join(', '));
                    }
                }
                // ###END###{MeshServerConnect}

                if (currentcomputer['ver']) {
                    var mode = '';
                    if (currentcomputer['pstate'] == 2) { mode = "ACM"; if (currentcomputer['pmode'] == 2) mode = "CCM"; }
                    if (mode != '') mode = ' / ' + mode;
                    x += addComputerDetailsEntry("Intel&reg; AMT", "v" + currentcomputer['ver'] + mode);
                }
                if (currentcomputer['date']) { x += addComputerDetailsEntry("Dernière connexion", new Date(currentcomputer['date']).toDateString()); }
                if (currentcomputer['digestrealm']) {
                    // ###BEGIN###{ContextMenus}
                    x += '<div cm="' + NoBreak("Supprimer le domaine ...") + '#removeCurrentRealm(' + currentcomputer['h'] + ')">';
                    // ###END###{ContextMenus}
                    x += addComputerDetailsEntry("Royaume de résumé", '<span style=font-size:x-small>' + currentcomputer['digestrealm'] + '</span><br /><span style=margin-left:5px><a style=cursor:pointer;font-size:10px;color:blue onclick=removeCurrentRealm(' + currentcomputer['h'] + ')><u>' + "Supprimer le domaine" + '</u></a></span>');
                    // ###BEGIN###{ContextMenus}
                    x += '</div>';
                    // ###END###{ContextMenus}
                }
                // ###BEGIN###{Mode-NodeWebkit}
                // ###BEGIN###{Certificates}
                if (currentcomputer['tlscerthash']) {
                    if (currentcomputer['tlscert']) {
                        // ###BEGIN###{ContextMenus}
                        x += '<div cm="' + NoBreak("Afficher le certificat ...") + '#viewCurrentPinCertificate(' + currentcomputer['h'] + ')|' + NoBreak("Supprimer l'épinglage ...") + '#removeCurrentPinCertificate(' + currentcomputer['h'] + ')">';
                        // ###END###{ContextMenus}
                        x += addComputerDetailsEntry("Certificat TLS", '<span title="Cert hash: ' + currentcomputer['tlscerthash'] + '">' + "Épinglé sur un certificat spécifique" + '</span><br /><span style=margin-left:5px><a style=cursor:pointer;font-size:10px;color:blue onclick=viewCurrentPinCertificate(' + currentcomputer['h'] + ')><u>' + "Afficher le certificat" + '</u></a> <a style=cursor:pointer;font-size:10px;color:blue onclick=removeCurrentPinCertificate(' + currentcomputer['h'] + ')><u>' + "Supprimer l'épinglage" + '</u></a></span>');
                        // ###BEGIN###{ContextMenus}
                        x += '</div>';
                        // ###END###{ContextMenus}
                    } else {
                        // ###BEGIN###{ContextMenus}
                        x += '<div cm="' + NoBreak("Supprimer l'épinglage ...") + '#removeCurrentPinCertificate(' + currentcomputer['h'] + ')">';
                        // ###END###{ContextMenus}
                        x += addComputerDetailsEntry("Certificat TLS", '<span title="Cert hash: ' + currentcomputer['tlscerthash'] + '">' + "Épinglé sur un certificat spécifique" + '</span><br /><span style=margin-left:5px><a style=cursor:pointer;font-size:10px;color:blue onclick=removeCurrentPinCertificate(' + currentcomputer['h'] + ')><u>' + "Supprimer l'épinglage" + '</u></a></span>');
                        // ###BEGIN###{ContextMenus}
                        x += '</div>';
                        // ###END###{ContextMenus}
                    }
                }
                // ###END###{Certificates}
                // ###END###{Mode-NodeWebkit}
                x += '</div>';

            }
            QH('id_computerDetails', x + bottomButtons + '</div>');
            computerSelect();
        }

        // ###BEGIN###{Look-Commander}
        // ###BEGIN###{!ComputerSelectorNoImages}
        function showIconSelector() {
            if (xxdialogMode) return;
            var x = '<br><div style=display:inline-block;width:40px></div>';
            x += '<div style=display:inline-block class=i1 onclick=setIcon(1)></div>';
            x += '<div style=display:inline-block class=i2 onclick=setIcon(2)></div>';
            x += '<div style=display:inline-block class=i3 onclick=setIcon(3)></div>';
            x += '<div style=display:inline-block class=i4 onclick=setIcon(4)></div>';
            x += '<div style=display:inline-block class=i5 onclick=setIcon(5)></div>';
            x += '<div style=display:inline-block class=i6 onclick=setIcon(6)></div>';
            setDialogMode(11, "Sélection d'icônes", 0, null, x);
            QV('id_dialogclose', true);
        }

        function setIcon(icon) {
            setDialogMode(0);
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) { meshCentralServer.send({ action: 'changedevice', nodeid: currentcomputer._id, icon: icon }); return; }
            // ###END###{MeshServerConnect}
            currentcomputer['icon'] = icon;
            // ###BEGIN###{ComputerSelector-Local}
            saveComputers();
            // ###END###{ComputerSelector-Local}
            updateComputerList();
        }
        // ###END###{!ComputerSelectorNoImages}
        // ###END###{Look-Commander}

        // ###BEGIN###{Mode-NodeWebkit}
        // ###BEGIN###{ContextMenus}
        // ###BEGIN###{Certificates}
        function viewCurrentPinCertificate(h) {
            if (xxdialogMode) return;
            var c = null;
            for (var x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }
            var cert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(hex2rstr(c['tlscert'])));
            var commonName = cert.subject.getField('CN').value;
            var fingerprint = '', fingerprint2 = forge.md.sha1.create().update(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()).digest().toHex().toUpperCase();
            for (i = 0; i < fingerprint2.length; i++) { if ((i != 0) && (i % 2 == 0)) { fingerprint += ':'; } fingerprint += fingerprint2.substring(i, i + 1); }
            var x = '<img src=images-commander/cert1.png style=float:right height=32 width=32 />';
            x += 'This certificate is pinned to computer ' + c['name'] + '. When connecting, if this certificate is received the connection will allowed. Hit delete button to un-pin.<br>';
            // ###BEGIN###{FileSaver}
            //x += addHtmlValue("Certificate", c.X509Certificate.length + " bytes, " + '<a style=cursor:pointer;color:blue onclick=downloadCert(' + h + ')>' + "Download" + '</a>');
            // ###END###{FileSaver}
            // ###BEGIN###{!FileSaver}
            //x += addHtmlValue("Certificate", c.X509Certificate.length + " bytes");
            // ###END###{!FileSaver}
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Objet du certificat" + '</i></div><br>';
            for (var i in xxCertSubjectNames) { var a = cert.subject.getField(i); if (a) { x += addHtmlValue(xxCertSubjectNames[i], EscapeHtml(a.value)); } }
            x += addHtmlValueNoTitle("Empreinte digitale", fingerprint.substring(0,29) + '<br />' + fingerprint.substring(30));
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificat d'émetteur" + '</i></div><br>';
            for (var i in xxCertSubjectNames) { var a = cert.issuer.getField(i); if (a) { x += addHtmlValue(xxCertSubjectNames[i], EscapeHtml(a.value)); } }
            setDialogMode(11, "Certificat -" + EscapeHtml(commonName), 5, function (b) { if (b == 2) { removeCurrentPinCertificateEx(2, h); } }, x);
        }

        function removeCurrentPinCertificate(h) {
            if (xxdialogMode) return;
            setDialogMode(11, "Épinglage de certificat", 3, removeCurrentPinCertificateEx, "Supprimer l'épinglage de certificat pour l'ordinateur sélectionné?", h);
        }

        function removeCurrentPinCertificateEx(button, h) {
            var c = null;
            for (var x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }
            if (c['tlscert']) delete c['tlscert'];
            if (c['tlscerthash']) delete c['tlscerthash'];
            storeCertPinning(c['host'], null);
            saveComputers();
            updateComputerList();
        }
        // ###END###{Certificates}
        // ###END###{ContextMenus}
        // ###END###{Mode-NodeWebkit}

        function removeCurrentRealm(h) {
            if (xxdialogMode) return;
            setDialogMode(11, "Royaume de résumé", 3, removeCurrentRealmEx, "Supprimer l'épinglage Digest Realm pour l'ordinateur sélectionné?", h);
        }

        function removeCurrentRealmEx(button, h) {
            var c = null;
            for (var x = 0; x < computerlist.length; x++) { if (computerlist[x]['h'] == h) { c = computerlist[x]; } }
            if (c['digestrealm']) delete c['digestrealm'];
            saveComputers();
            updateComputerList();
        }

        // ###BEGIN###{ComputerSelector-Local}
        function saveComputers() {
            if (urlvars['host']) return;
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) return;
            // ###END###{MeshServerConnect}
            // ###BEGIN###{Mode-NodeWebkit}
            const crypto = require('crypto');
            crypto.randomBytes(256, function(err, buf) {
                if (err) throw err; // Add trivial security, not intended to be real security. This just avoids storing data in plain text, but it's almost the same.
                var computerlist2 = JSON.parse(JSON.stringify(computerlist));
                for (var i in computerlist2) { delete computerlist2[i]['tlscert2']; delete computerlist2[i]['tlscerthash2']; } // Clean up the list
                var k = buf.toString('hex'), cipher = crypto.createCipher('aes-256-ctr', k), crypted = cipher.update(JSON.stringify(computerlist2), 'utf8', 'hex');
                crypted += cipher.final('hex');
                try { localStorage.setItem('computers', k + crypted); } catch (ex) { }
            });
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            try { localStorage.setItem('computers', JSON.stringify(computerlist)); } catch (ex) { }
            // ###END###{!Mode-NodeWebkit}
        }

        function loadComputers() {
            if (urlvars['host']) return;
            // ###BEGIN###{Mode-NodeWebkit}
            var ctext = null;
            try { ctext = localStorage.getItem('computers'); } catch (ex) { }
            if (ctext) {
                try { computerlist = JSON.parse(ctext); } catch (e) {
                    if (ctext.length > 512) { // Add trivial security, not intended to be real security. This just avoids storing data in plain text, but it's almost the same.
                        var crypto = require('crypto'), k = ctext.substring(0, 512), crypted = ctext.substring(512), decipher = crypto.createDecipher('aes-256-ctr', k), dec = decipher.update(crypted, 'hex', 'utf8');
                        dec += decipher.final('utf8');
                        try { computerlist = JSON.parse(dec); } catch (e) { computerlist = []; }
                        var pins = getCertPinnings();
                        for (var i in computerlist) {
                            computerlist[i].checked = false;
                            // Add stored certificate pinning.
                            if ((computerlist[i]['tlscerthash'] == null) && (pins[computerlist[i]['host']] != null)) { computerlist[i]['tlscerthash'] = pins[computerlist[i]['host']]; }
                            delete computerlist[i]['tlscert2'];
                            delete computerlist[i]['tlscerthash2'];
                        }
                    }
                }
            }
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            var ctext = null;
            try { ctext = localStorage.getItem('computers'); } catch (ex) { }
            if (ctext) { try { computerlist = JSON.parse(ctext); } catch (e) { computerlist = []; } }
            // ###END###{!Mode-NodeWebkit}
            updateComputerList();
            // ###BEGIN###{ComputerSelectorScanner}
            // ###BEGIN###{Mode-NodeWebkit}
            globalAmtScanner.performScan();
            // ###END###{Mode-NodeWebkit}
            // ###END###{ComputerSelectorScanner}
        }
        // ###END###{ComputerSelector-Local}

        function computerConnect(e, h, m, skipPass) {
            if (xxdialogMode) return;
            // ###BEGIN###{Mode-NodeWebkit}
            if ((m == 100) || (e && (e.shiftKey == true))) {
                // Launch a new instance of MeshCommander
                var adder = '';
                // ###BEGIN###{Desktop}
                if (m == 1) { adder = '&kvm=1'; }
                if (m == 2) { adder = '&kvmfull=1'; }
                if (m == 3) { adder = '&kvmonly=1'; }
                // ###END###{Desktop}
                // ###BEGIN###{Terminal}
                if (m == 4) { adder = '&sol=1'; }
                // ###END###{Terminal}
                var username = currentcomputer['user'];
                if (username == '') { username = 'admin'; }
                require('nw.gui').Window.open(window.location.href + '?host=' + currentcomputer['host'] + '&user=' + username + '&pass=' + currentcomputer['pass'] + '&tls=' + currentcomputer['tls'] + adder, { 'icon': 'favicon.png', 'toolbar': false, 'frame': true, 'width': 970, 'min_width': 970, 'height': 760, 'min_height': 640 });
                //require('child_process').exec('nw.exe -host:' + decodeURIComponent(currentcomputer['host']) + ' -user:' + decodeURIComponent(currentcomputer['user']) + ' -pass:' + decodeURIComponent(currentcomputer['pass']) + ((currentcomputer['tls']==1)?' -tls':''), function (error, stdout, stderr) { });
                return;
            }
            // ###END###{Mode-NodeWebkit}
            if (e) haltEvent(e);
            computerSelect(null, h);
            if (currentcomputer == null) return;
            if ((currentcomputer['user'] != '*') && (currentcomputer['pass'] == '')) {
                if (skipPass === true) { computerConnectLogin(9, m); return; }
                // Query for the login password
                var x = '<br>Enter the login password for ' + EscapeHtml(currentcomputer['name'] ? currentcomputer['name'] : currentcomputer['host']) + '.<br><br>';
                x += '<div style=height:26px><input id=d11connectUser onkeyup=computerConnectUpdateLogin() style=float:right;width:200px value="' + currentcomputer['user'] + '"><div>' + "Nom d'utilisateur" + '</div></div>';
                x += '<div style=height:26px><input id=d11connectPass onkeyup=computerConnectUpdateLogin(event) type=password style=float:right;width:200px><div>' + "Mot de passe" + '</div></div>';
                setDialogMode(11, "Identifiants de connexion", 3, computerConnectLogin, x);
                Q('d11connectPass').focus();
                computerConnectUpdateLogin();
            } else {
                // Go ahead and connect
                computerConnectLogin(0, m);
            }
        }

        function computerConnectUpdateLogin(e) {
            var ok = (Q('d11connectUser').value.length > 0) && (passwordcheck(Q('d11connectPass').value));
            QE('idx_dlgOkButton', ok);
            if ((e != undefined) && (e.keyCode == 13) && (ok == true)) { setDialogMode(0); computerConnectLogin(1, xxdialogTag); }
        }

        // If the user is prompted for a user/pass, we should not re-prompt after a certificate validation prompt.
        var skipPassUser = null;
        var skipPassPass = null;
        function computerConnectLogin(button, m) {
            var user = decodeURIComponent(currentcomputer['user']);
            var pass = decodeURIComponent(currentcomputer['pass']);
            if (button == 1) { user = Q('d11connectUser').value; pass = Q('d11connectPass').value; }
            if (button == 9) { user = skipPassUser; pass = skipPassPass; }
            skipPassUser = user;
            skipPassPass = pass;

            // Go ahead and connect
            var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
            if (user == '') { user = 'admin'; } // Default to admin if not specified.
            connect(ports.host, ports.http, user, pass, currentcomputer['tls'], function (mtag) {
                // ###BEGIN###{Mode-NodeWebkit}
                // If the fingerprint is set but not the certificate, set the cert.
                if (wsstack.comm.xtlsCertificate && (currentcomputer['tlscert'] == null) && (wsstack.comm.xtlsFingerprint == currentcomputer['tlscerthash'])) {
                    currentcomputer['tlscert'] = wsstack.comm.xtlsCertificate.raw.toString('hex');
                    updateComputerDetails();
                }
                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{Desktop}
                if (mtag == 1) { go(14); connectDesktop(); } // Go directly to remote desktop (1)
                if ((mtag == 2) || (mtag == 3)) { connectDesktop(); } // Go remote desktop fullscreen (2) and only remote desktop (3)
                // ###END###{Desktop}
                // ###BEGIN###{Terminal}
                if (mtag == 4) { go(13); connectTerminal(); } // Go directly to terminal (4)
                // ###END###{Terminal}
            }, m);
            if (m == 1) { go(14); }
            if ((m == 2) || (m == 3)) { go(14); deskToggleFull(m == 3); }
            if (m == 4) { go(13); }
        }

        function computerSelect(e, h) {
            if (h && ((currentcomputer == null) || (currentcomputer.h !== h))) { currentcomputer = getComputer(h); updateComputerDetails(); }
            for (var y in computerlist) {
                var computer = computerlist[y], sel = (currentcomputer != null && computer['h'] == currentcomputer['h']);
                QS('CI-' + computer['h'])['background-color'] = sel ? '#a0a0a0' : '#c9c9c9';
                Q('LCX-' + computer['h']).classList.remove('g1');
                Q('LCX-' + computer['h']).classList.remove('g1s');
                Q('RCX-' + computer['h']).classList.remove('g2');
                Q('RCX-' + computer['h']).classList.remove('g2s');
                Q('LCX-' + computer['h']).classList.add(sel?'g1s':'g1');
                Q('RCX-' + computer['h']).classList.add(sel?'g2s':'g2');
            }
        }

        function getComputer(h) { for (var i in computerlist) { if (computerlist[i]['h'] == h) return computerlist[i]; } return null; }

        // ###BEGIN###{Scripting}
        function mscript_showComputerScriptOutput(h) {
            if (xxdialogMode) return;
            var computer = getComputer(h);
            computer.consoledialog = 'scriptOutputArea';
            var name = computer['name'];
            if (!name) name = computer['host'];
            var v = '<textarea id=scriptOutputArea style=width:100%;height:150px;resize:vertical spellcheck=false readonly></textarea>';
            setDialogMode(11, "Sortie de script -" + name, 5, mscript_showComputerScriptOutputOk, v, computer);
            Q('scriptOutputArea').value = EscapeHtml(computer['consolemsgs']);
        }

        function mscript_showComputerScriptOutputOk(button, computer) {
            computer.consoledialog = undefined;
            if (button == 2) {
                if (computer.scriptstate) {
                    computer['consolemsgs'] = '';
                } else {
                    delete computer['consolemsgs'];
                    delete computer['consolemsg'];
                }
                saveComputers();
                updateComputerDetails();
            }
        }

        function mscript_runScriptDlg() {
            if (computersRunningScripts > 0) {
                // Stop all scripts
                for (var y in computerlist) {
                    var computer = computerlist[y];
                    if (computer.scriptstate) { computer.scriptstate.stop(); computer.scriptstate = undefined; }
                }
                updateComputerList();
            } else {
                // Start a new script dialog box
                if (xxdialogMode || scriptstate) return;
                var clist = [];
                for (var y in computerlist) { if (computerlist[y].checked == true) { clist.push(computerlist[y]); } }
                if (clist.length == 0) { clist.push(currentcomputer); }
                setDialogMode(11, "Script de lancement", 3, mscript_runScriptDlgOk, '<br>' + format("Exécuter un script sélectionné sur {0} ordinateur (s)", clist.length) + '.<br><br><input id=mscriptopen type=file style=width:100% accept=".mescript">');
            }
        }

        function mscript_runScriptDlgOk(r) {
            if (r != 1) return;
            var x = Q('mscriptopen');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = mscript_onScriptReadNoPrompt;
            reader.readAsBinaryString(x.files[0]);
        }

        function mscript_onScriptReadNoPrompt(file) { mscript_onScriptRead(file, 1); }
        function mscript_onScriptRead(file, noprompt) {
            if (computersRunningScripts > 0) return;
            var x, clist = [];
            try { x = JSON.parse(file.target.result); } catch (e) {}
            if (x && x['mescript']) {
                onComputerChecked();
                for (var y in computerlist) { if (computerlist[y].checked == true) { clist.push(computerlist[y]); } }
                if (clist.length == 0) { clist.push(currentcomputer); }
                x.clist = clist;
                if (noprompt == 1) {
                    mscript_onScriptReadOk(0, x);
                } else {
                    setDialogMode(11, "Script de lancement", 3, mscript_onScriptReadOk, format("Exécuter ce script sur {0} ordinateur (s)?", clist.length), x);
                }
            }
        }

        function mscript_onScriptReadOk(button, tag) {
            var x = tag;

            // ###BEGIN###{CertificateManager}
            var tlsoptions = {};

            // Create a list of trusted certificates in PEM format
            var trustedCertStringsPem = [];
            for (var y in certificateStore) {
                var certificate = certificateStore[y];
                if (certificate['trusted'] == true) { trustedCertStringsPem.push('-----BEGIN CERTIFICATE-----\n' + certificate['certbin'] + '\n-----END CERTIFICATE-----\n'); }
            }
            tlsoptions.ca = trustedCertStringsPem;

            // Setup out console TLS authentication certificate
            var authcert = getTlsAuthCertificate();
            if (authcert != null) {
                tlsoptions.cert = forge.pki.certificateToPem(authcert['cert']);
                tlsoptions.key = forge.pki.privateKeyToPem(authcert['privateKey']);
            }
            // ###END###{CertificateManager}

            for (var y in x.clist) {
                var mscriptstate, computer = x.clist[y], startvars = { '_interactive':0 };
                // ###BEGIN###{Certificates}
                startvars['_certificates'] = 1;
                // ###END###{Certificates}
                // ###BEGIN###{Mode-Firmware}
                startvars['_mode'] = 'Firmware';
                // ###END###{Mode-Firmware}
                // ###BEGIN###{Mode-MeshCentral2}
                startvars['_mode'] = 'MeshCentral2';
                // ###END###{Mode-MeshCentral2}
                // ###BEGIN###{Mode-NodeWebkit}
                startvars['_mode'] = 'NodeWebkit';
                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{Mode-LMS}
                startvars['_mode'] = 'LMS';
                // ###END###{Mode-LMS}
                // ###BEGIN###{Mode-WebSite}
                startvars['_mode'] = 'WebSite';
                // ###END###{Mode-WebSite}
                if (x && x['mescript']) mscriptstate = script_setup(atob(x['mescript']), startvars);
                if (mscriptstate) {
                    mscriptstate.computer = computer;
                    var ports = portsFromHost(computer['host'], computer['tls']);
                    // ###BEGIN###{CertificateManager}
                    mscriptstate.wsstack = WsmanStackCreateService(ports.host, ports.http, decodeURIComponent(computer['user']), decodeURIComponent(computer['pass']), computer['tls'], tlsoptions);
                    // ###END###{CertificateManager}
                    // ###BEGIN###{!CertificateManager}
                    mscriptstate.wsstack = WsmanStackCreateService(ports.host, ports.http, decodeURIComponent(computer['user']), decodeURIComponent(computer['pass']), computer['tls']);
                    // ###END###{!CertificateManager}
                    mscriptstate.amtstack = AmtStackCreateService(mscriptstate.wsstack);
                    mscriptstate.onStep = mscript_updateScriptState;
                    mscriptstate.onConsole = mscript_console;

                    // Setup TLS checking
                    // ###BEGIN###{Mode-NodeWebkit}
                    if (NW_TlsSecurityMode == 0) { mscriptstate.wsstack.comm.xtlsFingerprint = 0; }
                    else { mscriptstate.wsstack.comm.xtlsFingerprint = computer['tlscerthash'] ? computer['tlscerthash'] : computer['tlscerthash2']; }
                    // ###END###{Mode-NodeWebkit}

                    computer['consolemsg'] = '';
                    computer['consolemsgs'] = '';
                    computer.scriptstate = mscriptstate;
                    computer.scriptstate.start(100);
                } else {
                    messagebox("Script de lancement", "Fichier de script non valide.")
                    return;
                }
            }
            updateComputerList();
        }

        function mscript_updateScriptState(scriptstate) {
            if (scriptstate.state == 0) { scriptstate.computer.scriptstate = undefined; updateComputerList(); }
        }

        function mscript_console(msg, scriptstate) {
            scriptstate.computer['consolemsg'] = msg;
            scriptstate.computer['consolemsgs'] += (msg + '\r\n');
            if (scriptstate.computer.consoledialog) { Q(scriptstate.computer.consoledialog).value = scriptstate.computer['consolemsgs']; }
            QH('XI-' + scriptstate.computer['h'], msg);
        }

        function computerStopScript(e, h) {
            var computer = getComputer(h);
            if (computer.scriptstate) { computer.scriptstate.stop(); computer.scriptstate = undefined; }
            updateComputerList();
        }

        // ###END###{Scripting}

        //
        // MeshCentral Connection
        //
        // ###BEGIN###{MeshServerConnect}
        function showMeshCentralConnectDialog(showtoken) {
            if (xxdialogMode || meshCentralServer) return;
            var x = '<img src=\'images-commander/meshcentral50.png\' style=width:50px;height:50px;float:right></img><div>' + "Connect to a MeshCentral server and manage Intel&reg; AMT computers on that account." + '<div><br style=clear:both />';
            x += '<div style=height:26px><input id=meshserverurl value="" placeholder="sample.server.com:443" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Nom du serveur" + '</div></div>';
            x += '<div style=height:26px><input id=meshserverhash value="" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Hachage de certificat" + '</div></div>';
            x += '<div style=height:26px><input id=meshserveruser value="" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Nom d'utilisateur" + '</div></div>';
            x += '<div style=height:26px><input id=meshserverpass value="" type=password style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Mot de passe" + '</div></div>';
            if (showtoken) { x += '<div style=height:26px><input id=meshservertoken value="" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Jeton de connexion" + '</div></div>'; }
            //x += '<div style=height:26px><input id=meshserverproxy value="" placeholder="proxy.com:123" style=float:right;width:250px onkeyup=showMeshCentralConnectDialogUpdate()><div>' + "Proxy" + '</div></div>';
            setDialogMode(11, "MeshCentral Connect", 3, showMeshCentralConnectDialogOk, x);
            try {
                if (localStorage.getItem('meshserverurl')) { Q('meshserverurl').value = localStorage.getItem('meshserverurl'); }
                if (localStorage.getItem('meshserverhash')) { Q('meshserverhash').value = localStorage.getItem('meshserverhash'); }
                if (localStorage.getItem('meshserveruser')) { Q('meshserveruser').value = localStorage.getItem('meshserveruser'); }
                //if (localStorage.getItem('meshserverproxy')) { Q('meshserverproxy').value = localStorage.getItem('meshserverproxy'); }
            } catch (ex) { }
            showMeshCentralConnectDialogUpdate();
        }

        function showMeshCentralConnectDialogUpdate() {
            QS('meshserverurl')['background-color'] = ((Q('meshserverurl').value.length > 0) ? 'white' : 'LightYellow');
            QS('meshserveruser')['background-color'] = ((Q('meshserveruser').value.length > 0) ? 'white' : 'LightYellow');
            QS('meshserverpass')['background-color'] = ((Q('meshserverpass').value.length > 0) ? 'white' : 'LightYellow');
            var token = true;
            try { token = (Q('meshservertoken').value.length > 0); } catch (ex) { }
            QE('idx_dlgOkButton', token && (Q('meshserverurl').value.length > 0) && (Q('meshserveruser').value.length > 0) && (Q('meshserverpass').value.length > 0));
        }

        function showMeshCentralConnectDialogOk() {
            try {
                localStorage.setItem('meshserverurl', Q('meshserverurl').value);
                localStorage.setItem('meshserverhash', Q('meshserverhash').value);
                localStorage.setItem('meshserveruser', Q('meshserveruser').value);
            } catch (ex) { }
            var pass = Q('meshserverpass').value;
            var token = null;
            try { token = Q('meshservertoken').value; } catch (ex) { }
            //try { localStorage.setItem('meshserverproxy', Q('meshserverproxy').value); } catch (ex) { }
            var serverUrl = Q('meshserverurl').value;
            if (serverUrl.indexOf('://') < 0) { serverUrl = ('wss://' + serverUrl); }
            serverUrl = new URL(serverUrl);
            var serverPort = parseInt(serverUrl.port);
            if (isNaN(serverPort) || serverPort == 0) { serverPort = 443; }
            meshCentralServer = CreateMeshCentralServer(serverUrl.hostname, serverPort, '/control.ashx', Q('meshserveruser').value, Q('meshserverpass').value, token, Q('meshserverhash').value);
            meshCentralServer.onStateChange = function (sender, state, cause, msg) {
                var askForToken = false;
                if (state == 0) {
                    // Disconnected
                    loadComputers();
                    // If the connection failed due to hash mismatch, prompt the user.
                    disconnect();
                    QH('id_computername', format("Console de gestion à distance v{0}", version));
                    if (cause == 'HashMatchFail') { showTlsCert(3, "Connecté au serveur MeshCentral avec un certificat non reconnu. Cliquez sur OK pour accepter et vous connecter.", meshCentralServer.xtlsCertificate, meshCentralServer.password, meshCentralHashRetry); }
                    else if ((cause == 'noauth') && (msg == 'tokenrequired')) { askForToken = true; }
                    else if (cause == 'noauth') { setDialogMode(11, "Connexion MeshCentral", 1, null, "Nom d'utilisateur ou mot de passe invalide."); }
                    meshCentralServer = null;
                } else if (state == 1) {
                    // Connecting
                    currentcomputer = null;
                    computerlist = [];
                    QH('id_computername', 'Remote Management Console v' + version + ', Connecting to ' + meshCentralServer.host + '...');
                } else if (state == 3) {
                    // Connected
                    currentcomputer = null;
                    computerlist = meshCentralServer.computerlist;
                    meshCentralServer.xconnected = true;
                    QH('id_computername', 'Remote Management Console v' + version + ', Server: ' + meshCentralServer.host);
                }
                updateComputerList();
                NW_SetupMainMenu(currentView);

                if (askForToken) {
                    // Ask for 2-factor token and try again
                    showMeshCentralConnectDialog(true);
                    Q('meshserverpass').value = pass;
                    Q('meshservertoken').focus();
                    showMeshCentralConnectDialogUpdate();
                }
            }
            meshCentralServer.onNodeChange = function (sender, node) {
                //computerlist = meshCentralServer.computerlist;
                updateComputerList();
            }
            setDialogMode(0);
            meshCentralServer.connect();
        }

        // The user accepted the MeshCentral server hash, set it and try to connect again.
        function meshCentralHashRetry(b, args) {
            try { localStorage.setItem('meshserverhash', args.c.fingerprint.split(':').join('').toLowerCase()); } catch (ex) { }
            showMeshCentralConnectDialog();
            Q('meshserverpass').value = args.m; // Set the retry password
            showMeshCentralConnectDialogOk();
        }

        function meshCentralDisconnect() {
            if (meshCentralServer == null) return;
            meshCentralServer.disconnect();
            meshCentralServer = null;
            currentcomputer = null;
            updateComputerList();
        }
        // ###END###{MeshServerConnect}

        // ###BEGIN###{ComputerSelectorScanner}
        // ###BEGIN###{Mode-NodeWebkit}

        //
        // Network scan
        //

        var globalAmtScanner = CreateAmtScanner(amtScanChangePresence);
        var globalAmtScannerResults = null;

        function showScanDialog() {
            if (xxdialogMode) return;
            var x = "Entrez une plage d'adresses IP pour rechercher des périphériques Intel AMT." + '<br /><br />';
            x += '<div style=height:20px><div style=float:right;width:260px;overflow:hidden><input id=idx_iprange style=width:204px placeholder="192.168.0.0/16" onkeyup=showScanDialogUpdate()></input><input id=idx_iprangebutton type=button value=Scan onclick=amtScanStartScan()></input></b></div><div>' + "Plage ip" + '</div></div>';
            x += '<br /><div id=idx_results style="width:100%;height:200px;background-color:white;border:1px gray solid;overflow-y:scroll"></div>';
            setDialogMode(11, "Rechercher des appareils Intel&reg; AMT", 3, showScanDialogOk, x);
            QH('idx_results', '<div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>' + "Exemples de valeurs de plage IP" + '<br />192.168.0.100<br />192.168.0.0/16<br />192.168.0.1-192.168.0.100</div>');
            try { Q('idx_iprange').value = localStorage.getItem('scanrange'); } catch (ex) { }
            showScanDialogUpdate();
        }

        function showScanDialogUpdate() {
            QS('idx_iprange')['background-color'] = ((Q('idx_iprange').value.length > 0) ? 'white' : 'LightYellow');
            QE('idx_iprangebutton', Q('idx_iprange').value.length > 0);
            amtScanCheckbox();
        }

        // Populate the Intel AMT scan dialog box with the result of the RMCP scan
        function amtScanResult(scanner, result) {
            if ((xxdialogMode == undefined) || (!Q('idx_iprange'))) return;
            if (result == null) {
                // If no results where found, display a nice message
                QH('idx_results', '<div style=width:100%;text-align:center;margin-top:12px>Scan returned no results.</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>Sample IP range values<br />192.168.0.100<br />192.168.0.0/16<br />192.167.0.1-192.168.0.100</div>');
            } else {
                // Add the new result to the scan results dialog box
                var x = '', str = '<b>' + result.rinfo.address + '</b> - v' + result.ver;
                if (globalAmtScannerResults == null) { globalAmtScannerResults = {}; QH('idx_results', ''); }
                globalAmtScannerResults[result.rinfo.address] = result;
                if (result.state == 2) { if (result.tls == 1) { str += ' with TLS.'; } else { str += ' without TLS.'; } } else { str += ' not activated.'; }
                x += '<div style=margin-bottom:2px>';
                x += '<div class=j1 style=height:24px;float:left;background-color:white></div>';
                x += '<div class=g1 style=height:24px;float:left></div><div class=g2 style=height:24px;float:right></div><div style=height:24px;width:100%;background-color:#c9c9c9><div><div style=display:inline-block;margin-right:5px><input class=DevScanCheckbox tag="' + result.rinfo.address + '" type=checkbox onclick=amtScanCheckbox() /></div><div style=display:inline-block;margin-left:5px>' + str + '</div></div></div></div>';
                QA('idx_results', x);
            }
        }

        function amtScanStartScan() {
            var ip_range = Q('idx_iprange').value;
            try { localStorage.setItem('scanrange', ip_range); } catch (ex) { }
            globalAmtScannerResults = null;
            if (globalAmtScanner.performRangeScan('1', ip_range, amtScanResult) == false) {
                // The scan could not occur because of an error. Likely the user range was invalid.
                x = '<div style=width:100%;text-align:center;margin-top:12px>' + "Impossible de numériser cette plage d'adresses." + '</div><div style=width:100%;text-align:center;margin-top:12px;color:gray;line-height:1.5>' + "Exemples de valeurs de plage IP" + '<br />192.168.0.100<br />192.168.0.0/16<br />192.167.0.1-192.168.0.100</div>';
            } else {
                // Show scanning...
                QH('idx_results', '<div style=width:100%;text-align:center;margin-top:12px>' + "Balayage..." + '</div>');
            }
        }

        // Called when a scanned computer is checked or unchecked.
        function amtScanCheckbox() {
            var elements = document.getElementsByClassName('DevScanCheckbox'), checkcount = 0;
            for (var i in elements) { if (elements[i].checked) checkcount++; }
            QE('idx_dlgOkButton', checkcount > 0);
        }

        // Called when the OK button is pressed on the scan dialog
        function showScanDialogOk() {
            var elements = document.getElementsByClassName('DevScanCheckbox');
            for (var i in elements) {
                if (elements[i].checked) {
                    var ipaddr = elements[i].getAttribute('tag');
                    var result = globalAmtScannerResults[ipaddr];
                    computerlist.push({ 'h': Math.random(), 'name': ipaddr, 'host': ipaddr, 'tags': '', 'user': 'admin', 'pass': '', 'tls': result.tls, 'ver': result.ver });
                }
                saveComputers();
                updateComputerList();
            }
        }

        // Called by the scanner to change Intel AMT presense state
        function amtScanChangePresence(h, presence) {
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) return;
            // ###END###{MeshServerConnect}
            var element = Q('SS-' + h);
            if (element) { element.style['background-color'] = presence ? 'green' : 'red'; }

            // ###BEGIN###{Look-Commander}
            if (presence) { Q('SI-' + h).classList.remove('gray'); } else { Q('SI-' + h).classList.add('gray'); }
            // ###END###{Look-Commander}

            // If the computer that was updated is the current computer, update the details.
            if (currentcomputer && (currentcomputer.h == h)) { updateComputerDetails(); }
        }

        // Called when used clicks the "Scan for presense" menu option
        function NW_AmtScanMenu() {
            try { localStorage.setItem('scanForComputers', NW_AmtScanMenuItem.checked); } catch (ex) { }
            if (NW_AmtScanMenuItem.checked == true) { globalAmtScanner.start(); } else { globalAmtScanner.stop(); }
            updateComputerList();
        }

        // ###END###{Mode-NodeWebkit}
        // ###END###{ComputerSelectorScanner}

// ###END###{ComputerSelector}

// ###BEGIN###{ContextMenus}
        function handleContextMenu(e) {
            hideContextMenu();
            if (xxdialogMode) return;
            // ###BEGIN###{ComputerSelector}
            toolmenuclick(-1);
            // ###END###{ComputerSelector}
            var cm = document.elementFromPoint(e.pageX, e.pageY);
            while (cm && cm != null && cm.getAttribute('cm') == null) { cm = cm.parentElement; }
            if (cm && cm != null && cm.getAttribute('cm') != null) {
                var x = '', menus = cm.getAttribute('cm').split('|');
                if (cm.getAttribute('class') == 'computeritem') cm.click();
                for (var i in menus) {
                    if (menus[i] == '-') {
                        x += '<hr style="border:1px solid lightgray" />';
                    } else {
                        var menus2 = menus[i].split('#');
                        x += '<div class=cmtext onclick=\"hideContextMenu();' + menus2[1] + '\"><b>' + menus2[0] + '</b></div>';
                    }
                }
                QS('contextMenu').top = e.pageY + 'px';
                QS('contextMenu').left = e.pageX + 'px';
                QH('contextMenu', x);
                QV('contextMenu', true);
                haltEvent(e);
                return false;
            }
        }

        function hideContextMenu() { QV('contextMenu', false); }
// ###END###{ContextMenus}

        //
        // BOTTOM INFORMATION STRING
        //

// ###BEGIN###{VersionWarning}
        // Returns true if Intel AMT needs to be updated
        function checkAmtVersion(version) {
            var vSplit = version.split('.');
            var v1 = parseInt(vSplit[0]);
            var v2 = parseInt(vSplit[1]);
            var v3 = parseInt(vSplit[2]);
            var vx = ((v2 * 1000) + v3);
            var ok = 0;

            if ((v1 <= 5) || (v1 >= 12)) { ok = 1; } // Intel AMT less then v5 and v12 and beyond, all ok.
            else if ((v1 == 6) && (vx >= 2061)) { ok = 1; } // 1st Gen Core
            else if ((v1 == 7) && (vx >= 1091)) { ok = 1; } // 2st Gen Core
            else if ((v1 == 8) && (vx >= 1071)) { ok = 1; } // 3st Gen Core
            else if ((v1 == 9)) { if ((v2 < 5) && (vx >= 1041)) { ok = 1; } else if (vx >= 5061) { ok = 1; } } // 4st Gen Core
            else if ((v1 == 10) && (vx >= 55)) { ok = 1; } // 5st Gen Core
            else if (v1 == 11) {
                if ((v2 < 5) && (vx >= 25)) { ok = 1; } // 6st Gen Core
                else if (vx >= 6027) { ok = 1; } // 7st Gen Core
            }
            return (ok == 0);
        }
// ###END###{VersionWarning}

        function processSystemVersion(stack, name, responses, status) {
            if (status == 200 || status == 400) {
                var v;
                if (status == 200) {
                    //amtlogicalelements = responses;
                    amtlogicalelements = [];
                    if (responses != null) {
                        if (responses['CIM_SoftwareIdentity'] != null && responses['CIM_SoftwareIdentity'].responses != null) {
                            amtlogicalelements = responses['CIM_SoftwareIdentity'].responses;
                            if (responses['AMT_SetupAndConfigurationService'] != null && responses['AMT_SetupAndConfigurationService'].response != null) {
                                amtlogicalelements.push(responses['AMT_SetupAndConfigurationService'].response);
                            }
                        }
                    }
                    if (amtlogicalelements.length == 0) { console.error('ERROR: Could not get Intel AMT version.'); disconnect(); return; } // Could not get Intel AMT version, disconnect();
                    v = getInstance(amtlogicalelements, 'AMT')['VersionString'];
                } else {
                    v = stack.wsman.comm.amtVersion;
                    if (!v) { errcheck(400, stack); return; }
                }
                amtversion = parseInt(v.split('.')[0]);
                amtversionmin = parseInt(v.split('.')[1]);

                // If this is Intel AMT 16 or higher, boost the stack speed by allowing HTTP pipelining.
                //if (amtversion > 15) {
                    //stack.MaxActiveEnumsCount = 2;
                    //stack.wsman.comm.MaxActiveAjaxCount = 2;
                //}

                // ###BEGIN###{Mode-NodeWebkit}
                // Perform Intel ME authentication if available.
                if ((amtversion >= 15) && (wsstack.comm.xtlsCertificate != null)) {
                    stack.amtauthnonce = require('crypto').randomBytes(20).toString('base64');
                    stack.AMT_GeneralSettings_AMTAuthenticate(stack.amtauthnonce, function (stack, name, response, status) {
                        //console.log('AMTAuthenticate', status, response);
                        //status = 200;
                        //response = JSON.parse('{"Header":{"To":"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous","RelatesTo":"15","Action":"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings/AMTAuthenticateResponse","MessageID":"uuid:00000000-8086-8086-8086-00000000008E","ResourceURI":"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings","Method":"AMTAuthenticate"},"Body":{"Nonce":"s5PzXOyJqlPwnE/FJ1Imk2tLc2s=","UUID":"465A544C39335830B0304A51465A544C","FQDN":"","FWVersion":"15.0.10.7000","AMTSVN":1,"Signature":"cT4DpT2VpDi0jq+3tIswntXIIitCQV6QxMbXMZryob7RYRyazW9YFKrX5nfu0tPpTqLEP9P+C8pVT4ZngU1TIrn2ptVw/xCKmOn56Y62U0Gv+fQSG1+AJFRej+W7Clv4","LengthOfCertificates":[602,638,631,708],"Certificates":"MIICVjCCAd2gAwIBAgIQSsxzEcw7W5elVuRWfkbN1zAKBggqhkjOPQQDAzAeMRwwGgYDVQQDDBNDU01FIFRHTCBBTVQgIDAxU0RFMB4XDTIwMDcyMzAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowFTETMBEGA1UEAwwKQU1UIFdTLU1BTjB2MBAGByqGSM49AgEGBSuBBAAiA2IABOiUImnj9foD828QWknCF47SuIhwKn+AzhcgPz7IaUb/Z9KTPn57VfxahHBObijKRodtcxao0Jip/0sM3wbXkHvF03BLdxP6/ab5uMYLH+ZDjdlwC69qkjQtXciIzml8u6OB6DCB5TAfBgNVHSMEGDAWgBS4jxQZFu/qvArLmfxFoa+HO3ZPhjAPBgNVHRMBAf8EBTADAQEAMA4GA1UdDwEB/wQEAwIGgDCBoAYDVR0fBIGYMIGVMIGSoEqgSIZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY3Jscy9PbkRpZV9DQV9DU01FX0luZGlyZWN0LmNybKJEpEIwQDEmMCQGA1UECwwdT25EaWUgQ0EgQ1NNRSBJbnRlcm1lZGlhdGUgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wCgYIKoZIzj0EAwMDZwAwZAIwMlkcpHt5ydDt2hmnF+pJxLzH6oF3K2XPviuudyQ8DtHfuziWXgI7t2KS/Y5tOFEAAjBxLW0MkEcpDlsKNS0ASNxOhi6neEEQaxT93EJh3J/Z0SU8qYdE2/qtfe087XhCvlowggJ6MIICAaADAgECAgUBBBwAIDAKBggqhkjOPQQDAzAjMSEwHwYDVQQDDBhDU01FIFRHTCBTVk4wMSBLZXJuZWwgREUwHhcNMjAwNzIzMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjAeMRwwGgYDVQQDDBNDU01FIFRHTCBBTVQgIDAxU0RFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAES/XBgK8rDlDycUzCocI1TrrrcQzD2Okq2BJhfqSg6MKxRMyei903Ewl94yl+tFsWoLuPiZDVE/bfxJghTynuGxk38YI8Qn8L3mPL+ahh3tSxWxC3kdszrU9dgObLF+2Io4IBCDCCAQQwHwYDVR0jBBgwFoAUzxraD/dMy5Zf2FiUKGctnPWwk30wHQYDVR0OBBYEFLiPFBkW7+q8CsuZ/EWhr4c7dk+GMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMIGgBgNVHR8EgZgwgZUwgZKgSqBIhkZodHRwczovL3RzREUuaW50ZWwuY29tL2NvbnRlbnQvT25EaWVDQS9jcmxzL09uRGllX0NBX0NTTUVfSW5kaXJlY3QuY3JsokSkQjBAMSYwJAYDVQQLDB1PbkRpZSBDQSBDU01FIEludGVybWVkaWF0ZSBDQTEWMBQGA1UEAwwNd3d3LmludGVsLmNvbTAKBggqhkjOPQQDAwNnADBkAjBiU4sHamrnSkvkwpTbVJah30CSGycVSwlUCUnXxFBFcCmXQeuXdElJiXhZyO5CQf8CMBxnQghoKlmUCKhzEYHjDMdXAKJcIapz6ksRDuYycxOlEpyBjei5tU5Nq16qDdt0njCCAnMwggH5oAMCAQICAQEwCgYIKoZIzj0EAwMwGjEYMBYGA1UEAwwPQ1NNRSBUR0wgUk9NIERFMB4XDTIwMDcyMzAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowIzEhMB8GA1UEAwwYQ1NNRSBUR0wgU1ZOMDEgS2VybmVsIERFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEtfPOoxER7WKkOQQFPnDBikHOrIkNZA1si7sFV1Y1tSBF4HCCl0BfXo5GqsOxzwJ2JcJLiP16ZP3rMcOOpufVLwPwN/0jmP1/KDeANgmwGLLvjAuHfx/KRU3MqkDdSLbfo4IBCDCCAQQwHwYDVR0jBBgwFoAUsd+j/J4YMaOrY0I0x9dKYND8mMQwHQYDVR0OBBYEFM8a2g/3TMuWX9hYlChnLZz1sJN9MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKsMIGgBgNVHR8EgZgwgZUwgZKgSqBIhkZodHRwczovL3RzREUuaW50ZWwuY29tL2NvbnRlbnQvT25EaWVDQS9jcmxzL09uRGllX0NBX0NTTUVfSW5kaXJlY3QuY3JsokSkQjBAMSYwJAYDVQQLDB1PbkRpZSBDQSBDU01FIEludGVybWVkaWF0ZSBDQTEWMBQGA1UEAwwNd3d3LmludGVsLmNvbTAKBggqhkjOPQQDAwNoADBlAjB0WjT9RuE7v+dm2EM2uf7uZ3Pv3KAKZzBkpvokIbuO1qE3FS36mf3kKfl58hMhfosCMQD4NyxKd28cm9ZfW7eOEetEwXXDgCtq+rfzCXbJWDQvkYpnS4LPxIXxEsiN6/scTH0wggLAMIICRqADAgECAhBAAAAAAAAAAAAAAAAAAAAAMAoGCCqGSM49BAMDMEgxLjAsBgNVBAsMJU9uIERpZSBDU01FIERfVEdMIERFQlVHMDAwIElzc3VpbmcgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wHhcNMTkwMTAxMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjAaMRgwFgYDVQQDDA9DU01FIFRHTCBST00gREUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ4g65/2ziA9osYJXOdQ81/PobyJmcTqSU8CMcVk3OyWhGjaczREvl+DvZpd5+2CYAxSr3ItlK5Jn3z1xG4mwHRzH0FFdu7Ooxf7kSH5dXnSO7hv6q/y97+KTy6odfzRuqjggEhMIIBHTAfBgNVHSMEGDAWgBQ7McrVw0uS10jI/ZKqda6dMkoGQjAdBgNVHQ4EFgQUsd+j/J4YMaOrY0I0x9dKYND8mMQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAa4wYgYIKwYBBQUHAQEEVjBUMFIGCCsGAQUFBzAChkZodHRwczovL3RzREUuaW50ZWwuY29tL2NvbnRlbnQvT25EaWVDQS9jZXJ0cy9UR0xfREVCVUcwMDBfT25EaWVfQ0EuY2VyMFYGA1UdHwRPME0wS6BJoEeGRWh0dHBzOi8vdHNERS5pbnRlbC5jb20vY29udGVudC9PbkRpZUNBL2NybHMvVEdMX0RFQlVHMDAwX09uRGllX0NBLmNybDAKBggqhkjOPQQDAwNoADBlAjAjX8BHXjQGsr1uqkCDdqRRzT2yQNLU4i85H+mJboRaAB2h09mISKagGU0m3DXywmICMQDmTjjpPjCJye9m2u/csfkUAn7rP1FLmdJHtT9qN968CACWQQ356e8s3XgNpNtexJU=","ReturnValue":0,"ReturnValueStr":"SUCCESS"}}'); // Sample Response 1
                        //response = JSON.parse('{"Header":{"To":"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous","RelatesTo":"15","Action":"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings/AMTAuthenticateResponse","MessageID":"uuid:00000000-8086-8086-8086-0000000000F8","ResourceURI":"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings","Method":"AMTAuthenticate"},"Body":{"Nonce":"NlfyHfo322EtefP1q5s92K+szBw=","UUID":"465A544C39335830B0304A51465A544C","FQDN":"","FWVersion":"15.0.10.7000","AMTSVN":1,"Signature":"9jBx0HfvNECPrMrg16px2RGDu/qdgrUyguOamlJ5hpiYgt9ZPrMz6/WgYY5nbnT6zBxSTUP+AqEzcmA6oWunYHZQJprY9iDdew4PPIHWqGZGgqh/10m3aYHwy+TKk/Ab","LengthOfCertificates":[603,638,631,708],"Certificates":"MIICVzCCAd2gAwIBAgIQSsxzEcw7W5elVuRWfkbN1zAKBggqhkjOPQQDAzAeMRwwGgYDVQQDDBNDU01FIFRHTCBBTVQgIDAxU0RFMB4XDTIwMDcyMzAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowFTETMBEGA1UEAwwKQU1UIFdTLU1BTjB2MBAGByqGSM49AgEGBSuBBAAiA2IABOiUImnj9foD828QWknCF47SuIhwKn+AzhcgPz7IaUb/Z9KTPn57VfxahHBObijKRodtcxao0Jip/0sM3wbXkHvF03BLdxP6/ab5uMYLH+ZDjdlwC69qkjQtXciIzml8u6OB6DCB5TAfBgNVHSMEGDAWgBS4jxQZFu/qvArLmfxFoa+HO3ZPhjAPBgNVHRMBAf8EBTADAQEAMA4GA1UdDwEB/wQEAwIGgDCBoAYDVR0fBIGYMIGVMIGSoEqgSIZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY3Jscy9PbkRpZV9DQV9DU01FX0luZGlyZWN0LmNybKJEpEIwQDEmMCQGA1UECwwdT25EaWUgQ0EgQ1NNRSBJbnRlcm1lZGlhdGUgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wCgYIKoZIzj0EAwMDaAAwZQIwYCfw7GuUi9XxfBfhO/LYUbSb3pd65tkpRSLjIhsj9uMG9DFbMVUy9aicvZt7NYwXAjEAtAdHvcmoI/fZfw2Mo7TooojLe+xfHzZ5NyZyVlPaVyya25K/3kE05gvQO1jvk/ZcMIICejCCAgGgAwIBAgIFAQQcACAwCgYIKoZIzj0EAwMwIzEhMB8GA1UEAwwYQ1NNRSBUR0wgU1ZOMDEgS2VybmVsIERFMB4XDTIwMDcyMzAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowHjEcMBoGA1UEAwwTQ1NNRSBUR0wgQU1UICAwMVNERTB2MBAGByqGSM49AgEGBSuBBAAiA2IABEv1wYCvKw5Q8nFMwqHCNU6663EMw9jpKtgSYX6koOjCsUTMnovdNxMJfeMpfrRbFqC7j4mQ1RP238SYIU8p7hsZN/GCPEJ/C95jy/moYd7UsVsQt5HbM61PXYDmyxftiKOCAQgwggEEMB8GA1UdIwQYMBaAFM8a2g/3TMuWX9hYlChnLZz1sJN9MB0GA1UdDgQWBBS4jxQZFu/qvArLmfxFoa+HO3ZPhjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDCBoAYDVR0fBIGYMIGVMIGSoEqgSIZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY3Jscy9PbkRpZV9DQV9DU01FX0luZGlyZWN0LmNybKJEpEIwQDEmMCQGA1UECwwdT25EaWUgQ0EgQ1NNRSBJbnRlcm1lZGlhdGUgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wCgYIKoZIzj0EAwMDZwAwZAIwYlOLB2pq50pL5MKU21SWod9AkhsnFUsJVAlJ18RQRXApl0Hrl3RJSYl4WcjuQkH/AjAcZ0IIaCpZlAiocxGB4wzHVwCiXCGqc+pLEQ7mMnMTpRKcgY3oubVOTateqg3bdJ4wggJzMIIB+aADAgECAgEBMAoGCCqGSM49BAMDMBoxGDAWBgNVBAMMD0NTTUUgVEdMIFJPTSBERTAeFw0yMDA3MjMwMDAwMDBaFw00OTEyMzEyMzU5NTlaMCMxITAfBgNVBAMMGENTTUUgVEdMIFNWTjAxIEtlcm5lbCBERTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLXzzqMREe1ipDkEBT5wwYpBzqyJDWQNbIu7BVdWNbUgReBwgpdAX16ORqrDsc8CdiXCS4j9emT96zHDjqbn1S8D8Df9I5j9fyg3gDYJsBiy74wLh38fykVNzKpA3Ui236OCAQgwggEEMB8GA1UdIwQYMBaAFLHfo/yeGDGjq2NCNMfXSmDQ/JjEMB0GA1UdDgQWBBTPGtoP90zLll/YWJQoZy2c9bCTfTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICrDCBoAYDVR0fBIGYMIGVMIGSoEqgSIZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY3Jscy9PbkRpZV9DQV9DU01FX0luZGlyZWN0LmNybKJEpEIwQDEmMCQGA1UECwwdT25EaWUgQ0EgQ1NNRSBJbnRlcm1lZGlhdGUgQ0ExFjAUBgNVBAMMDXd3dy5pbnRlbC5jb20wCgYIKoZIzj0EAwMDaAAwZQIwdFo0/UbhO7/nZthDNrn+7mdz79ygCmcwZKb6JCG7jtahNxUt+pn95Cn5efITIX6LAjEA+DcsSndvHJvWX1u3jhHrRMF1w4Aravq38wl2yVg0L5GKZ0uCz8SF8RLIjev7HEx9MIICwDCCAkagAwIBAgIQQAAAAAAAAAAAAAAAAAAAADAKBggqhkjOPQQDAzBIMS4wLAYDVQQLDCVPbiBEaWUgQ1NNRSBEX1RHTCBERUJVRzAwMCBJc3N1aW5nIENBMRYwFAYDVQQDDA13d3cuaW50ZWwuY29tMB4XDTE5MDEwMTAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowGjEYMBYGA1UEAwwPQ1NNRSBUR0wgUk9NIERFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEOIOuf9s4gPaLGCVznUPNfz6G8iZnE6klPAjHFZNzsloRo2nM0RL5fg72aXeftgmAMUq9yLZSuSZ989cRuJsB0cx9BRXbuzqMX+5Eh+XV50ju4b+qv8ve/ik8uqHX80bqo4IBITCCAR0wHwYDVR0jBBgwFoAUOzHK1cNLktdIyP2SqnWunTJKBkIwHQYDVR0OBBYEFLHfo/yeGDGjq2NCNMfXSmDQ/JjEMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGuMGIGCCsGAQUFBwEBBFYwVDBSBggrBgEFBQcwAoZGaHR0cHM6Ly90c0RFLmludGVsLmNvbS9jb250ZW50L09uRGllQ0EvY2VydHMvVEdMX0RFQlVHMDAwX09uRGllX0NBLmNlcjBWBgNVHR8ETzBNMEugSaBHhkVodHRwczovL3RzREUuaW50ZWwuY29tL2NvbnRlbnQvT25EaWVDQS9jcmxzL1RHTF9ERUJVRzAwMF9PbkRpZV9DQS5jcmwwCgYIKoZIzj0EAwMDaAAwZQIwI1/AR140BrK9bqpAg3akUc09skDS1OIvOR/piW6EWgAdodPZiEimoBlNJtw18sJiAjEA5k446T4wicnvZtrv3LH5FAJ+6z9RS5nSR7U/ajfevAgAlkEN+envLN14DaTbXsSV","ReturnValue":0,"ReturnValueStr":"SUCCESS"}}'); // Sample Response 2

                        if (status == 200) {
                            stack.amtauth = response.Body;
                            stack.amtauth.CertificatesDer = [];
                            var certs = [], urlList = [], certsbin = atob(stack.amtauth.Certificates), cptr = 0;
                            for (var i = 0; i < stack.amtauth.LengthOfCertificates.length; i++) {
                                var bin = certsbin.substring(cptr, cptr + stack.amtauth.LengthOfCertificates[i]);
                                stack.amtauth.CertificatesDer.push(bin);
                                var cert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(bin)); // Node-forge does not support ECC, but we are using a modified Node-forge that can still parse the cert.
                                cert.xCrlUrls = getExtensionUrls(cert, 'cRLDistributionPoints');
                                cert.xParentUrls = getExtensionUrls(cert, { id: '1.3.6.1.5.5.7.1.1' });
                                cert.xFingerprint = forge.md.sha256.create().update(bin).digest().toHex().toUpperCase();
                                cptr += stack.amtauth.LengthOfCertificates[i];
                                certs.push(cert);
                                if ((cert.xCrlUrls.length > 0) && (urlList.indexOf(cert.xCrlUrls[0]) == -1)) { urlList.push(cert.xCrlUrls[0]); }
                            }

                            // If the top certificate has a parent URL, add it to the list of URL's to fetch.
                            if ((certs.length > 0) && (certs[certs.length - 1].xParentUrls.length > 0) && (urlList.indexOf(certs[certs.length - 1].xParentUrls[0]) == -1)) {
                                urlList.push(certs[certs.length - 1].xParentUrls[0]);
                            }

                            stack.amtauth.Certificates = certs;
                            stack.amtauth.ClientNonce = stack.amtauthnonce;
                            delete stack.amtauth.LengthOfCertificates;
                            stack.amtauth.uuidStr = guidToStr(stack.amtauth.UUID).toLowerCase();

                            var trustedCsmeRoots = [
                                '3BA13766B1889DCB1E2D55BACCC9EC087452F78783E2EBAFD918FF4ED6ACC840', // www.intel.com / OnDie CA DEBUG Root Cert Signing CA
                                'C001DF02B31A60A2B37130365956400A2AFCFD147E8552FD7EA3F17F2AB0D457', // www.intel.com / ODCA CA2 CSME Intermediate CA
                                '5E3EEE5748AC13E0B3D1227FCDC4751AA1402DDE8031D21F63CB4ECF43F02440'  // www.intel.com / OnDie CA CSME Intermediate CA
                            ];

                            // Load the entire certificate chain and CRL's
                            var urlLoad = function (url, data) {
                                if (data == null) return;
                                for (var j in certs) {
                                    if ((certs[j].xCrlUrls.length > 0) && (certs[j].xCrlUrls[0] == url)) { certs[j].xCrl = data; }
                                    if ((j == (certs.length - 1)) && (certs[j].xParentUrls.length > 0) && (certs[j].xParentUrls[0] == url)) {
                                        var xcert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(data)); // Node-forge does not support ECC, but we are using a modified Node-forge that can still parse the cert.
                                        xcert.xCrlUrls = getExtensionUrls(xcert, 'cRLDistributionPoints');
                                        xcert.xParentUrls = getExtensionUrls(xcert, { id: '1.3.6.1.5.5.7.1.1' });
                                        xcert.xFingerprint = forge.md.sha256.create().update(data).digest().toHex().toUpperCase();
                                        if (trustedCsmeRoots.indexOf(xcert.xFingerprint) >= 0) { xcert.xTrusted = true; }
                                        certs.push(xcert);
                                        stack.amtauth.CertificatesDer.push(data);
                                        if ((xcert.xCrlUrls.length > 0) && (urlList.indexOf(xcert.xCrlUrls[0]) == -1)) { getCertUrl(xcert.xCrlUrls[0], urlLoad); }
                                        if ((xcert.xParentUrls.length > 0) && (urlList.indexOf(xcert.xParentUrls[0]) == -1)) { urlList.push(xcert.xParentUrls[0]); getCertUrl(xcert.xParentUrls[0], urlLoad); }
                                        return;
                                    }
                                }
                            }
                            for (var i in urlList) { getCertUrl(urlList[i], urlLoad); }
                        } else {
                            console.log('AMTAuthenticate', status, response);
                        }
                        delete stack.amtauthnonce;
                    });
                }
                // ###END###{Mode-NodeWebkit}

                // ###BEGIN###{ComputerSelector}
                if (stack.wsman.comm.digestRealm && (currentcomputer['digestrealm'] != stack.wsman.comm.digestRealm)) {
                    currentcomputer['digestrealm'] = stack.wsman.comm.digestRealm;
                    // ###BEGIN###{ComputerSelector-Local}
                    saveComputers();
                    // ###END###{ComputerSelector-Local}
                    updateComputerDetails();
                }
                // ###END###{ComputerSelector}

                // ###BEGIN###{VersionWarning}
                QV('id_versionWarning', checkAmtVersion(v));
                // ###END###{VersionWarning}
                // ###BEGIN###{!Mode-Firmware}
                //if (amtversion > 10) { wsstack.comm.MaxActiveAjaxCount = 4; amtstack.MaxActiveEnumsCount = 1; console.log('HTTP Pipelining activated'); } // With Intel AMT 11 and higher, use HTTP pipelining.
                // ###END###{!Mode-Firmware}

                PullSystemStatus();
                updateSystemStatus();

                // Perform loads more WSMAN only if needed
                if ((urlvars['kvmonly'] != 1) && (fullscreenonly == false)) {
                    PullUserInfo();

                    // ###BEGIN###{Alarms}
                    if (amtversion >= 8) PullAlarms();
                    // ###END###{Alarms}
                }

                // ###BEGIN###{Mode-NodeWebkit}
                if (wsstack.comm.getPeerCertificate() != null) {
                    QV('tlsNotification1', wsstack.comm.xtlsCheck == 1);
                    QV('tlsNotification2', wsstack.comm.xtlsCheck == 2);
                    QV('tlsNotification3', wsstack.comm.xtlsCheck == 3);
                }
                if (currentcomputer['tlscerthash2']) delete currentcomputer['tlscerthash2'];
                if (currentcomputer['tlscert2']) delete currentcomputer['tlscert2'];
                // ###END###{Mode-NodeWebkit}

                // Connection callback
                if (connectFunc) { connectFunc(connectFuncTag); connectFunc = null; connectFuncTag = null; }

                // ###BEGIN###{Desktop}
                if (urlvars['kvm'] == 1) { go(14); connectDesktop(); }
                if ((urlvars['kvmfull'] == 1) || (urlvars['kvmonly'] == 1)) { go(14); connectDesktop(); }
                // ###END###{Desktop}
                // ###BEGIN###{Terminal}
                if (urlvars['sol'] == 1) { go(13); connectTerminal(); }
                // ###END###{Terminal}

                // ###BEGIN###{Scripting}
                // ###BEGIN###{Mode-NodeWebkit}
                // ###BEGIN###{!ComputerSelector-Local-ScriptOnly}
                if (urlvars['host'] && urlvars['script']) {
                    try {
                        var data = require('fs').readFileSync(urlvars['script'], 'utf8');
                        if (data) { script_onScriptRead( { target: { result: data }} ); }
                    } catch (e) { messagebox("Script de lancement", "Fichier de script non valide.") }
                }
                // ###END###{!ComputerSelector-Local-ScriptOnly}
                // ###END###{Mode-NodeWebkit}
                // ###END###{Scripting}
            } else {
                errcheck(status, stack);
            }
        }

        // Control the state of all refresh buttons
        var refreshButtonsState = true;
        function refreshButtons(x) {
            if (refreshButtonsState == x) return;
            refreshButtonsState = x;
            var i = 0, e = document.getElementsByTagName('input');
            for (; i < e.length; i++) { if (e[i].name == 'refreshbtn') { e[i].disabled = !x; } }
        }

        // Store certificate pinning
        // ###BEGIN###{Mode-NodeWebkit}
        function storeCertPinning(host, hash) {
            var pins = {};
            try { pins = JSON.parse(localStorage.getItem('amtcertpins')); } catch (e) { }
            if ((pins == null) || (typeof pins != 'object')) { pins = {}; }
            if (hash) { pins[host] = hash; } else { delete pins[host]; }
            try { localStorage.setItem('amtcertpins', JSON.stringify(pins)); } catch (ex) { }
        }

        function getCertPinnings() { try { var x = JSON.parse(localStorage.getItem('amtcertpins')); if ((x == null) || (typeof x != 'object')) return {}; return x; } catch (e) { return {} } }
        function getCertPinning(host) { return getCertPinnings()[host]; }

        // ###END###{Mode-NodeWebkit}

        // Display TLS certificate
        // ###BEGIN###{Mode-NodeWebkit}
        var showTlsCertTempCert;
        function showTlsCert(buttons, msg, cert, tag, func) {
            if (xxdialogMode) return;
            var c = showTlsCertTempCert = cert?cert:wsstack.comm.getPeerCertificate(), x = '<br>';
            if (msg) x = '<div>' + msg + '</div><br />';
            // ###BEGIN###{FileSaver}
            x += addHtmlValue("Certificat", c.raw.length + " octets," + '<a style=cursor:pointer;color:blue onclick=downloadTlsCert()>' + "Télécharger" + '</a>');
            // ###END###{FileSaver}
            // ###BEGIN###{!FileSaver}
            x += addHtmlValue("Certificat", c.raw.length + " octets");
            // ###END###{!FileSaver}

            // Display certificate key usages
            var y = [];
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.2') >= 0) { y.push(NoBreak("Client TLS")); }
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.3') >= 0) { y.push(NoBreak("Signature du code")); }
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.4') >= 0) { y.push("Email"); }
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.1') >= 0) { y.push(NoBreak("Serveur TLS")); }
            if (c.ext_key_usage.indexOf('2.16.840.1.113741.1.2.1') >= 0) { y.push(NoBreak("Console Intel&reg; AMT")); }
            if (c.ext_key_usage.indexOf('2.16.840.1.113741.1.2.2') >= 0) { y.push(NoBreak("Agent Intel&reg; AMT")); }
            if (c.ext_key_usage.indexOf('2.16.840.1.113741.1.2.3') >= 0) { y.push(NoBreak("Activation Intel&reg; AMT")); }
            if (c.ext_key_usage.indexOf('1.3.6.1.5.5.7.3.8') >= 0) { y.push(NoBreak("Horodatage")); }
            if (y.length > 0) { x += addHtmlValueNoTitle("Utilisation du certificat", y.join(', ') + '.') + '<br clear=all />'; }

            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Objet du certificat" + '</i></div><br>';
            for (var i in c.subject) { if (c.subject[i]) { x += addHtmlValue(xxCertSubjectNames[i] ? xxCertSubjectNames[i] : i, EscapeHtml(MakeToArray(c.subject[i]).join(', '))); } }
            x += addHtmlValueNoTitle("Empreinte digitale", c.fingerprint.substring(0,29) + '<br />' + c.fingerprint.substring(30));
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificat d'émetteur" + '</i></div><br>';
            for (var i in c.issuer) { if (c.issuer[i]) { x += addHtmlValue(xxCertSubjectNames[i] ? xxCertSubjectNames[i] : i, EscapeHtml(MakeToArray(c.issuer[i]).join(', '))); } }
            if (func == null) { func = showTlsCertDefault; }
            setDialogMode(11, "Certificat TLS -" + EscapeHtml(c.subject['CN']), buttons, func, x, { c: c, m: tag });
        }

        function showTlsCertDefault(b, args) {
            var cert = args.c, mode = args.m;
            if (b == 0) { disconnect(); }
            if (b == 1) {
                currentcomputer['tlscerthash'] = cert.fingerprint.split(':').join('').toLowerCase();
                currentcomputer['tlscert'] = cert.raw.toString('hex');
                currentcomputer['tlscerthash2'] = cert.fingerprint.split(':').join('').toLowerCase();
                currentcomputer['tlscert2'] = cert.raw.toString('hex');
                storeCertPinning(currentcomputer.host, cert.fingerprint.split(':').join('').toLowerCase());
                // ###BEGIN###{ComputerSelector-Local}
                saveComputers();
                // ###END###{ComputerSelector-Local}
                updateComputerDetails();
                if (mode == 1) {
                    // Reconnect immidiatly
                    computerConnect(undefined, currentcomputer['h'], 0, true);
                }
            }
        }

        function downloadTlsCert() {
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', showTlsCertTempCert.subject['CN'] + '.cer');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, showTlsCertTempCert.raw, 'binary', function () { }); }, false);
            chooser.click();
        }

        function switchToTls() {
            if (xxTlsCurrentCert == null) {
                setDialogMode(11, "Passer à TLS", 3, switchToTls1, "La connexion n'est actuellement pas sécurisée. Cliquez sur OK pour configurer Intel AMT avec TLS et basculer vers une connexion sécurisée.");
            } else {
                setDialogMode(11, "Passer à TLS", 3, switchToTls1, "La connexion n'est actuellement pas sécurisée et Intel AMT est déjà configuré avec TLS. Cliquez sur OK pour basculer vers une connexion sécurisée.");
            }
        }

        function switchToTls1() {
            // Check if Intel AMT is already setup with TLS.
            if (xxTlsCurrentCert == null) {
                // TLS is not setup, start by asking Intel AMT to generate a key pair
                messagebox("Configuration TLS", "Génération de la clé de certificat ...");
                amtstack.AMT_PublicKeyManagementService_GenerateKeyPair(0, 2048, switchToTls2);
            } else {
                // Setup the certificate pinning and reconnect
                var cert = null;
                try { cert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(xxCertificates[xxTlsCurrentCert].X509Certificate)); } catch (ex) { messagebox("Certificat TLS", "Impossible de lire le certificat TLS: " + ex); return; }
                currentcomputer['tlscert'] = forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).toHex();
                currentcomputer['tlscerthash'] = forge.md.sha1.create().update(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()).digest().toHex();
                currentcomputer['tls'] = 1;
                updateComputerDetails();
                saveComputers();

                // Disconnect and reconnect immidiatly
                disconnect();
                computerConnect(undefined, currentcomputer['h'], 0, true);
            }
        }

        function switchToTls2(stack, serviceName, response, status) {
            if (status != 200) { messagebox("Délivrer un certificat", "Impossible de générer la paire de clés. Statut: " + status); return; }
            if (response.Body['ReturnValue'] != 0) { messagebox("Délivrer un certificat", "Impossible de générer la paire de clés," + response.Body['ReturnValueStr']); return; }

            // Get the new key pair
            messagebox("Configuration TLS", "Récupération de la clé de certificat ...");
            amtstack.Enum('AMT_PublicPrivateKeyPair', switchToTls3, response.Body['KeyPair']['ReferenceParameters']['SelectorSet']['Selector']['Value']);
        }

        function switchToTls3(stack, serviceName, response, status, tag) {
            if (status != 200) { messagebox("Délivrer un certificat", "Impossible de générer la paire de clés. Statut: " + status); return; }
            var DERKey = null;
            for (var i in response) { if (response[i]['InstanceID'] == tag) DERKey = response[i]['DERKey']; }

            // Sign the key pair using the CA certifiate
            messagebox("Configuration TLS", "Création d'un certificat TLS ...");

            var name = ''
            try { name = amtsysstate['AMT_GeneralSettings'].response['HostName']; } catch (ex) { }
            if ((name == null) || (name == '')) { name = currentcomputer['name']; }
            if ((name == null) || (name == '')) { name = currentcomputer['host']; }
            var cert = amtcert_signWithCaKey(DERKey, null, { 'CN': name, 'O': "Aucun", 'ST': "Aucun", 'C': "Aucun" }, { 'CN': "Certificat racine non approuvé" }, { name: 'extKeyUsage', serverAuth: true });
            if (cert == null) { messagebox("Délivrer un certificat", "Impossible de signer le certificat."); return; }

            // Save cert and cert hash in computer list
            messagebox("Configuration TLS", "Téléchargement du certificat TLS ...");
            currentcomputer['tlscert'] = forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).toHex();
            currentcomputer['tlscerthash'] = forge.md.sha1.create().update(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()).digest().toHex();
            updateComputerDetails();
            saveComputers();

            // Place the resulting signed certificate back into AMT
            var pem = forge.pki.certificateToPem(cert).replace(/(\r\n|\n|\r)/gm, '');
            amtstack.AMT_PublicKeyManagementService_AddCertificate(pem.substring(27, pem.length - 25), switchToTls4);
        }

        function switchToTls4(stack, serviceName, response, status) {
            if (status != 200) { messagebox("Délivrer un certificat", "Impossible de générer la paire de clés. Statut: " + status); return; }

            messagebox("Configuration TLS", "Définition du certificat TLS ...");
            var certInstanceId = response.Body['CreatedCertificate']['ReferenceParameters']['SelectorSet']['Selector']['Value'];

            // Set the TLS certificate
            setTlsSecurityPendingCalls = 3;
            if (xxTLSCredentialContext.length > 0) {
                // Modify the current context
                var newTLSCredentialContext = Clone(xxTLSCredentialContext[0]);
                newTLSCredentialContext['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'] = certInstanceId;
                amtstack.Put('AMT_TLSCredentialContext', newTLSCredentialContext, switchToTls5, 0, 1);
            } else {
                // Add a new security context
                amtstack.Create('AMT_TLSCredentialContext', {
                    'ElementInContext': '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + certInstanceId + '</w:Selector></w:SelectorSet></a:ReferenceParameters>',
                    'ElementProvidingContext': '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_TLSProtocolEndpointCollection') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="ElementName">TLSProtocolEndpointInstances Collection</w:Selector></w:SelectorSet></a:ReferenceParameters>'
                }, switchToTls5);
            }

            // Figure out what index is local & remote
            var localNdx = ((xxTlsSettings[0]['InstanceID'] == 'Intel(r) AMT LMS TLS Settings')) ? 0 : 1, remoteNdx = (1 - localNdx);

            // Remote TLS settings
            var xxTlsSettings2 = Clone(xxTlsSettings);
            xxTlsSettings2[remoteNdx]['Enabled'] = true;
            xxTlsSettings2[remoteNdx]['MutualAuthentication'] = false;
            xxTlsSettings2[remoteNdx]['AcceptNonSecureConnections'] = true;
            delete xxTlsSettings2[remoteNdx]['TrustedCN'];

            // Local TLS settings
            xxTlsSettings2[localNdx]['Enabled'] = true;
            delete xxTlsSettings2[localNdx]['TrustedCN'];

            // Update TLS settings
            amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[0], switchToTls5, 0, 1, xxTlsSettings2[0]);
            amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[1], switchToTls5, 0, 1, xxTlsSettings2[1]);
        }

        function switchToTls5(stack, name, response, status) {
            if (stack) {
                if (status != 200) { messagebox('', "Impossible de définir le certificat TLS, état =" + status); return; }
                if (response.Body['ReturnValueStr'] && !methodcheck(response)) return;
            }

            // Check if all the calls are done & perform a commit
            if ((--setTlsSecurityPendingCalls) == 0) {
                messagebox("Configuration TLS", "Exécution de la validation ...");
                amtstack.AMT_SetupAndConfigurationService_CommitChanges(null, switchToTls6);
            }
        }

        function switchToTls6(stack, name, response, status) {
            if (status != 200) { messagebox('', "Impossible de définir la sécurité TLS, état =" + status); return; }
            if (response.Body['ReturnValue'] != 0) { messagebox('', "Impossible de définir la sécurité TLS, erreur: " + response.Body['ReturnValueStr']); return; }

            // Switch current computer to TLS
            messagebox("Configuration TLS", "Configuration TLS terminée.");
            currentcomputer['tls'] = 1;
            updateComputerDetails();
            saveComputers();

            setTimeout(function () {
                setDialogMode();

                // Disconnect and reconnect immidiatly
                disconnect();
                computerConnect(undefined, currentcomputer['h'], 0, true);
            }, 2000);
        }

        // ###END###{Mode-NodeWebkit}

        //
        // SYSTEM STATUS PANEL
        //

        // ###BEGIN###{PowerControl}
        function PullPowerState() {
            if (amtstack && amtstack.GetPendingActions() == 0 && amtsysstate && amtsysstate['CIM_ServiceAvailableToElement']) {
                amtstack.Enum('CIM_ServiceAvailableToElement', function (stack, name, responses, status) {
                    if (status != 200) return; // If the polling fails, just skip it.
                    amtsysstate['CIM_ServiceAvailableToElement'].responses = responses;
                    if ((amtversion > 9) && (amtsysstate['CIM_ServiceAvailableToElement'] != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses.length > 0) && (amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] == 2)) {
                        // If Intel AMT 10+ and powered on, poll the OS power state.
                        amtstack.Get('IPS_PowerManagementService', function (stack, name, response, status) {
                            if (status == 200) { amtsysstate['IPS_PowerManagementService'].response = response.Body; updateSystemStatus(); }
                        });
                    } else {
                        updateSystemStatus();
                    }
                });

            }
        }
        // ###END###{PowerControl}

        function PullSystemStatus(x) {
            refreshButtons(false);
            amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(processSystemTime);
            // ###BEGIN###{Look-Intel-SBT}
            amtstack.BatchEnum('', ['*AMT_GeneralSettings'], processSystemStatus);
            // ###END###{Look-Intel-SBT}
            // ###BEGIN###{!Look-Intel-SBT}
            var query = ['CIM_ServiceAvailableToElement', '*AMT_GeneralSettings', 'AMT_EthernetPortSettings', '*AMT_RedirectionService', 'CIM_ElementSettingData', '*AMT_BootCapabilities'];
            if (amtversion > 5) query.push('IPS_IPv6PortSettings', '*CIM_KVMRedirectionSAP', '*IPS_OptInService','*IPS_KVMRedirectionSettingData');
            if (amtversion > 9) query.push('*IPS_ScreenConfigurationService', '*IPS_PowerManagementService');
            if (amtversion > 15) query.push('*CIM_BootService');
            // ###BEGIN###{NetAuth}
            if (amtversion > 2) query.push('*AMT_8021XProfile');
            // ###END###{NetAuth}
            amtstack.BatchEnum('', query, processSystemStatus, true);
            // ###END###{!Look-Intel-SBT}
            // ###BEGIN###{Wireless}
            if (x == 1) PullWireless();
            // ###END###{Wireless}
        }

        function processSystemTime(stack, name, responses, status) {
            if (errcheck(status, stack)) return;
            if (status == 200) {
                // Convert ms to time and adjust for the timezone
                var t = new Date(), t2 = new Date();
                //t.setTime(responses.Body['Ta0'] * 1000 + (t.getTimezoneOffset() * 60 * 1000));
                t.setTime(responses.Body['Ta0'] * 1000);
                amtdeltatime = t - t2;
                updateSystemStatus();
            }
        }

        var amtdeltatime;
        var amtsysstate;
        var amtlogicalelements; // processSystemVersion
        var amtfeatures = {};
        function processSystemStatus(stack, name, responses, status) {
            // ###BEGIN###{ComputerSelector}
            if (wsstack == null || amtstack != stack) return;
            // ###END###{ComputerSelector}
            // If this computer has no KVM, ignore and continue (Standard Manageability)
            if ((responses['IPS_ScreenConfigurationService'] == undefined) || (responses['IPS_ScreenConfigurationService'].status == 400)) { responses['IPS_ScreenConfigurationService'] = null; }
            if ((responses['IPS_KVMRedirectionSettingData'] == undefined) || (responses['IPS_KVMRedirectionSettingData'].status == 400)) { responses['IPS_KVMRedirectionSettingData'] = null; }
            if ((responses['CIM_KVMRedirectionSAP'] == undefined) || (responses['CIM_KVMRedirectionSAP'].status == 400)) { responses['CIM_KVMRedirectionSAP'] = null; }
            if ((responses['IPS_OptInService'] == undefined) || (responses['IPS_OptInService'].status == 400)) { responses['IPS_OptInService'] = null; }
            if ((responses['AMT_RedirectionService'] != undefined) && (responses['AMT_RedirectionService'].status == 200)) { QV('go13', true); } // Show the terminal
            
            // Reset the status after possible KVM removal
            status = 0;
            for (var i in responses) { if ((responses[i] != null) && (responses[i].status > status)) { status = responses[i].status; } }

            if ((status != 400) && errcheck(status, stack)) return;
            amtsysstate = responses;
            applyDesktopSettings();
            updateSystemStatus();
        }

        // Ask to synchronize the Intel AMT clock
        function syncClock() {
            if (xxdialogMode) return;
            setDialogMode(11, "Synchroniser l'horloge", 3, syncClockEx, "Synchroniser l'horloge Intel AMT avec cet ordinateur?");
        }

        // Synchronize the Intel AMT clock
        function syncClockEx() {
            amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(function (stack, name, response, status) {
                if (status != 200) { messagebox('', "Impossible de régler l'heure, état =" + status); return; }
                if (response.Body['ReturnValue'] != 0) { messagebox('', "Impossible de régler l'heure, erreur: " + response.Body['ReturnValueStr']); return; }
                //var now = new Date(), Tm1 = Math.round((now.getTime() - (now.getTimezoneOffset() * 60000)) / 1000);
                var now = new Date(), Tm1 = Math.round(now.getTime() / 1000);
                amtstack.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch(response.Body['Ta0'], Tm1, Tm1, function () { amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(processSystemTime); });
            });
        }

        // ###BEGIN###{PowerControl}
        var DMTFPowerStates = ['', '', "Allumer", "Sommeil léger", "Sommeil profond", "Cycle d'alimentation (Soft off)", "Arrêt - Difficile", "Hibernation (Off soft)", "Arrêt progressif", "Cycle d'alimentation (hors tension)", "Réinitialisation du bus principal", "Interruption de diagnostic (NMI)", "N'est pas applicable", "Off - doux gracieux", "Off - Gracieux dur", "Réinitialisation du bus maître gracieuse", "Cycle d'alimentation (Off - Soft graceful)", "Cycle d'alimentation (Off - Hard graceful)", "Interruption de diagnostic (INIT)"];
        // ###END###{PowerControl}
        function updateSystemStatus() {
            if ((!amtsysstate) || (currentView > 99)) return;

            // System Status Table
            var systemdefense = 0, host, y, x = TableStart(), features = '', gs = amtsysstate['AMT_GeneralSettings'].response;
            // ###BEGIN###{PowerControl}
            var t = '<i>' + "Inconnue" + '</i>';
            if ((amtsysstate['CIM_ServiceAvailableToElement'] != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses.length > 0)) {
                t = DMTFPowerStates[amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState']];
                // If Intel AMT 10+, check OS power saving state.
                if ((amtversion > 9) && (t == "Allumer") && (amtsysstate['IPS_PowerManagementService']) && (amtsysstate['IPS_PowerManagementService'].response) && (amtsysstate['IPS_PowerManagementService'].response['OSPowerSavingState'] == 3)) { t = 'Standby (Connected)'; }
                // ###BEGIN###{Terminal}
                QH('id_p13power', t); // Display the power state on the terminal form
                // ###END###{Terminal}
                // ###BEGIN###{Desktop}
                //if ((desktop.State != 0) && (Q('id_p14power').innerHTML.length > 0) && (Q('id_p14power').innerHTML != t)) { desktop.Stop(); setTimeout(connectDesktop, 150); }
                QH('id_p14power', t); // Display the power state on the desktop form
                // ###END###{Desktop}
            }
            if (gs['PowerSource']) t += [", Branché", ", Sur la batterie"][gs['PowerSource']];
            x += TableEntry("Puissance", addLink(t, 'showPowerActionDlg()'));
            // ###END###{PowerControl}

            host = gs['HostName'];
            y = gs['DomainName'];
            if (y != null && y.length > 0) host += '.' + y;
            if (host.length == 0) { host = ('<i>' + "Aucun" + '</i>'); } else { host = EscapeHtml(host); }
            x += TableEntry("Nom et domaine", addLinkConditional(host, 'showEditNameDlg()', xxAccountAdminName));
            if (amtstack.amtauth && amtstack.amtauth.uuidStr) {
                x += TableEntry("ID système", amtstack.amtauth.uuidStr);
            } else if (HardwareInventory) {
                x += TableEntry("ID système", guidToStr(HardwareInventory['CIM_ComputerSystemPackage'].response['PlatformGUID'].toLowerCase()));
            }
            if (amtlogicalelements) {
                var mode = '', scs = getItem(amtlogicalelements, 'CreationClassName', 'AMT_SetupAndConfigurationService');
                // ###BEGIN###{!Look-Intel-SBT}
                if ((scs['ProvisioningState'] == 2) && (amtversion > 5)) {
                    mode = " activé en mode de contrôle administrateur (ACM)";
                    if (scs['ProvisioningMode'] == 4) { mode = " activé en mode de contrôle client (CCM)"; systemdefense = 9; }
                }
                // ###END###{!Look-Intel-SBT}

                // ###BEGIN###{Look-Intel-SBT}
                x += TableEntry("Intel&reg; SBT", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Intel-SBT}
                // ###BEGIN###{Look-Intel-SM}
                x += TableEntry("Intel&reg; SM", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Intel-SM}
                // ###BEGIN###{Look-Intel-AMT}
                x += TableEntry("Intel&reg; AMT", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Intel-AMT}
                // ###BEGIN###{Look-Commander}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Commander}
                // ###BEGIN###{Look-ISDU}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-ISDU}
                // ###BEGIN###{Look-BrandedCommander}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-BrandedCommander}
                // ###BEGIN###{Look-Unite}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-Unite}
                // ###BEGIN###{Look-MeshCentral}
                x += TableEntry("Intel&reg; ME", 'v' + getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'] + mode);
                // ###END###{Look-MeshCentral}

                // ###BEGIN###{ComputerSelector}
                currentcomputer['ver'] = getItem(amtlogicalelements, 'InstanceID', 'AMT')['VersionString'];
                currentcomputer['pstate'] = scs['ProvisioningState'];
                currentcomputer['pmode'] = scs['ProvisioningMode'];
                currentcomputer['date'] = new Date().toISOString();
                updateComputerDetails();
                // ###BEGIN###{ComputerSelector-Local}
                saveComputers();
                // ###END###{ComputerSelector-Local}
                // ###END###{ComputerSelector}
            }

            // ###BEGIN###{!Mode-MeshCentral2}

            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                QH('id_computername', "Ordinateur: " + ((gs['HostName'] == '') ? ('<i>' + "Aucun" + '</i>') : gs['HostName']) + ", Serveur: " + meshCentralServer.host);
            } else {
                QH('id_computername', "Ordinateur: " + ((gs['HostName'] == '') ? ('<i>' + "Aucun" + '</i>') : gs['HostName']));
            }
            // ###END###{MeshServerConnect}
            // ###BEGIN###{!MeshServerConnect}
            QH('id_computername', "Ordinateur: " + ((gs['HostName'] == '') ? ('<i>' + "Aucun" + '</i>') : gs['HostName']));
            // ###END###{!MeshServerConnect}

            // ###END###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-NodeWebkit}
            if (gs['HostName'] != '') { require('nw.gui').Window.get().title = NW_WindowTitle + ' - ' + gs['HostName']; } else { require('nw.gui').Window.get().title = NW_WindowTitle; }
            // ###END###{Mode-NodeWebkit}

            // ###BEGIN###{PowerControl}
            if ((amtsysstate['CIM_ServiceAvailableToElement'] != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses.length > 0)) {
                // Intel AMT power state warning. If computer is not powered on, display a warning in terminal and desktop panels.
                // ###BEGIN###{Terminal}
                QV('id_p13warning2', amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] != 2);
                // ###END###{Terminal}
                // ###BEGIN###{Desktop}
                QV('id_p14warning2', amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] != 2);
                // ###END###{Desktop}
            }
            // ###END###{PowerControl}

            // ###BEGIN###{!Look-Intel-SBT}
            // Intel AMT Features
            if (amtsysstate['AMT_RedirectionService'].status == 200) {
                var redir = amtfeatures[0] = (amtsysstate['AMT_RedirectionService'].response['ListenerEnabled'] == true);
                var sol = amtfeatures[1] = ((amtsysstate['AMT_RedirectionService'].response['EnabledState'] & 2) != 0);
                var ider = amtfeatures[2] = ((amtsysstate['AMT_RedirectionService'].response['EnabledState'] & 1) != 0);
                var kvm = amtfeatures[3] = undefined;
                if ((amtversion > 5) && (amtsysstate['CIM_KVMRedirectionSAP'] != null)) {
                    // ###BEGIN###{Desktop}
                    QV('go14', true); // Desktop
                    // ###END###{Desktop}
                    kvm = amtfeatures[3] = ((amtsysstate['CIM_KVMRedirectionSAP'].response['EnabledState'] == 6 && amtsysstate['CIM_KVMRedirectionSAP'].response['RequestedState'] == 2) || amtsysstate['CIM_KVMRedirectionSAP'].response['EnabledState'] == 2 || amtsysstate['CIM_KVMRedirectionSAP'].response['EnabledState'] == 6);
                }
                if (redir) features += ", Port de redirection";
                if (sol) features += ", Série sur LAN";
                if (ider) features += ", IDE-Redirect";
                if (kvm) features += ", KVM";
                if (features == '') features = '  ' + "Aucun";
                x += TableEntry("Fonctionnalités actives", addLinkConditional(features.substring(2), 'showFeaturesDlg()', xxAccountAdminName));
            }

            if ((amtsysstate['IPS_KVMRedirectionSettingData'] != null) && (amtsysstate['IPS_KVMRedirectionSettingData'].response)) {
                var desktopSettings = amtsysstate['IPS_KVMRedirectionSettingData'].response;
                var screenname = "Affichage principal";
                if ((amtversion > 7) && (desktopSettings['DefaultScreen'] !== undefined) && (desktopSettings['DefaultScreen'] < 255)) { screenname = ["Affichage principal", "Affichage secondaire", "3e affichage"][desktopSettings['DefaultScreen']]; }
                features = '<span title="' + format("L'affichage à distance par défaut est {0}", screenname.toLowerCase()) + '">' + screenname + '</span>';
                if (desktopSettings['Is5900PortEnabled'] == true) { features += ", Port 5900 activé"; }
                if (desktopSettings['OptInPolicy'] == true) { features += "," + desktopSettings['OptInPolicyTimeout'] + ' ' + ((desktopSettings['OptInPolicyTimeout'] > 0)?"opt-in secondes":"deuxième opt-in"); }
                features += "," + desktopSettings['SessionTimeout'] + " minute" + ((desktopSettings['SessionTimeout'] > 0) ? 's' : '') + " expiration de la session";

                // Screen blanking on AMT 10 and higher
                if ((amtversion > 9) && (amtsysstate['IPS_ScreenConfigurationService'] != null)) {
                    var screenBlanking = ((amtsysstate['IPS_ScreenConfigurationService'].response['EnabledState'] & 1) != 0);
                    if (screenBlanking) features += ", Masquage autorisé";
                    // ###BEGIN###{Desktop}
                    QV('id_DeskSBspan', screenBlanking);
                    Q('id_DeskSB').checked = false;
                    // ###END###{Desktop}
                } else {
                    // ###BEGIN###{Desktop}
                    QV('id_DeskSBspan', false);
                    // ###END###{Desktop}
                }

                // ###BEGIN###{Desktop-Settings}
                x += TableEntry("Bureau à distance", addLinkConditional(features, 'showDesktopSettingsDlg()', xxAccountAdminName));
                // ###END###{Desktop-Settings}
                // ###BEGIN###{!Desktop-Settings}
                x += TableEntry("Bureau à distance", features);
                // ###END###{!Desktop-Settings}
            }
            // ###BEGIN###{Terminal}
            QV('id_p13warning1', !redir || !sol); // Show the warning box on top of the terminal if redirection or sol is disabled.
            QV('id_p13warninga', xxAccountAdminName); // If we are not administrator, we can't activate SOL.
            // ###END###{Terminal}
            // ###BEGIN###{Desktop}
            QV('id_p14warning1', !redir || !kvm); // Show the warning box on top of the remote desktop viewer if redirection or kvm is disabled.
            QV('id_p14warninga', xxAccountAdminName); // If we are not administrator, we can't activate KVM.
            // ###END###{Desktop}

            // Intel AMT user Consent
            if ((amtversion > 5) && (amtsysstate != null && amtsysstate['IPS_OptInService'] != null) && (amtsysstate['IPS_OptInService'].response != undefined)) {
                features = "État inconnu";
                var optinrequired = amtsysstate['IPS_OptInService'].response['OptInRequired'];
                if (optinrequired == 0) { features = "Non requis"; }
                if (optinrequired == 1) { features = "Requis pour KVM uniquement"; }
                if (optinrequired == 0xFFFFFFFF) { features = "Toujours requis"; }
                if (amtsysstate['IPS_OptInService'].response['CanModifyOptInPolicy'] == true) features = addLinkConditional(features, 'showConsentDlg()', xxAccountAdminName); // If we can modify user consent settings, add the link to do it.
                x += TableEntry("Consentement de l'utilisateur", features);
            }

            // Power Options
            if ((amtsysstate['AMT_BootCapabilities'].response['PlatformErase'] != null) && (amtsysstate['AMT_BootCapabilities'].response['PlatformErase'] > 0) && (amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] != null)) {
                var enabledBootStateStr = { 0: "Inconnue", 1: "Autre", 2: "Activée", 3: "désactivé", 4: "Éteindre", 5: "N'est pas applicable", 6: "Activé mais hors ligne", 7: "En test", 8: "Différé", 9: "Au repos", 10: "Départ", 32768: "OCR Disabled", 32769: "OCR Enabled", 32770: "OCR Disabled, RPE Enabled", 32771: "RPE & OCR Enabled" };
                if (amtversion > 15) { enabledBootStateStr[32768] = "OCR & RPE Disabled"; enabledBootStateStr[32769] = "OCR Enabled, RPE Disabled"; }
                var t = enabledBootStateStr[amtsysstate['CIM_BootService'].response['EnabledState']]?enabledBootStateStr[amtsysstate['CIM_BootService'].response['EnabledState']]:"Inconnue";
                x += TableEntry("Boot Features", addLinkConditional(t, 'showEnableBootServiceDlg()', xxAccountAdminName));
            }

            // Intel AMT Power policy
            if (AmtSystemPowerSchemes != null) {
                var elementSettings = amtsysstate['CIM_ElementSettingData'].responses;
                for (var i = 0; i < elementSettings.length; i++) {
                    if (elementSettings[i]['SettingData'] && elementSettings[i]['IsCurrent'] == 1 && elementSettings[i]['SettingData']['ReferenceParameters']['ResourceURI'] == 'http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SystemPowerScheme') {
                        // Found the active Intel AMT power scheme
                        var powerguid = elementSettings[i]['SettingData']['ReferenceParameters']['SelectorSet']['Selector'][1]['Value'];
                        // Now find the name of the power schema in the AMT_SystemPowerScheme table
                        for (var j = 0; j < AmtSystemPowerSchemes.length; j++) {
                            if (AmtSystemPowerSchemes[j]['SchemeGUID'] == powerguid) {
                                // Found the power scheme name
                                x += TableEntry("Politique d'alimentation", addLinkConditional(AmtSystemPowerSchemes[j]['Description'].split(':' )[1], 'showPowerPolicyDlg(\"' + powerguid + '\")', xxAccountAdminName));
                            }
                        }
                    }
                }
            }
            // ###END###{!Look-Intel-SBT}

            if (amtdeltatime) { x += TableEntry("Date et heure", addLinkConditional(new Date(new Date().getTime() + amtdeltatime).toLocaleString(), 'syncClock()', xxAccountAdminName)); }
            var buttons = AddRefreshButton('PullSystemStatus()') + ' ';
            // ###BEGIN###{PowerControl}
            buttons += AddButton("Actions de puissance ...", 'showPowerActionDlg()') + ' ';
            // ###END###{PowerControl}
            // ###BEGIN###{WsmanBrowser}
            // ###BEGIN###{FileSaver}
            buttons += AddButton("Enregistrer l'état ...", 'saveEntireAmtState()') + ' ';
            // ###END###{FileSaver}
            // ###END###{WsmanBrowser}
            // ###BEGIN###{Scripting}
            buttons += AddButton("Script de lancement...", 'script_runScriptDlg()') + ' ';
            // ###END###{Scripting}
            x += TableEnd(buttons);

            // Show authentic CSME if present
            if (amtstack.amtauth) { x += '<div style=position:absolute;top:10px;right:20px;cursor:pointer onclick=showAuthCsme()><img src=authcsme.png width=100 height=100 /></div>'; }

            QH('id_TableSysStatus', x);

            // ###BEGIN###{NetworkSettings}
            var x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px>';
            x += TableEnd('<div>&nbsp;' + AddRefreshButton('PullSystemStatus(1)')
                // ###BEGIN###{!Mode-LMS}
                + " La modification des paramètres réseau peut rendre cette page indisponible."
                // ###END###{!Mode-LMS}
                // ###BEGIN###{Mode-LMS}
                + " Changing network settings may cause this page to be unavailable for a few seconds."
                // ###END###{Mode-LMS}
            );

            // General settings
            x += '<br><h2>' + "réglages généraux" + '</h2>';
            x += TableStart();

            // Network state
            // if (gs['AMTNetworkEnabled']) { x += TableEntry("Network state", (gs['AMTNetworkEnabled']==1)?"Enabled":"Disabled"); }

            // Shared FQDN
            var fqdnshare = '';
            if (host != '<i>' + "Aucun" + '</i>') {
                if (gs['SharedFQDN'] == true) fqdnshare = ", partagé avec OS";
                if (gs['SharedFQDN'] == false) fqdnshare = ", différent du système d'exploitation";
            }
            x += TableEntry("Nom et domaine", addLinkConditional(host + fqdnshare, 'showEditNameDlg(1)', xxAccountAdminName));

            // Dynamic DNS
            var ddns = "désactivé";
            if (gs['DDNSUpdateEnabled'] == true) {
                ddns = "Activé chacun" + gs['DDNSPeriodicUpdateInterval'] + " minutes, TTL est" + gs['DDNSTTL'] + " minutes";
            } else if (gs['DDNSUpdateByDHCPServerEnabled'] == true) {
                ddns = "Mise à jour par serveur DHCP";
            }
            x += TableEntry("DNS dynamique", addLinkConditional(ddns, 'showEditDnsDlg()', xxAccountAdminName));
            x += TableEnd();

            for (var y in amtsysstate['AMT_EthernetPortSettings'].responses) {
                var z = amtsysstate['AMT_EthernetPortSettings'].responses[y];
                if (z['WLANLinkProtectionLevel'] || (y == 1)) { amtwirelessif = y; } // Set the wireless interface, this seems to cover new wireless only computers and older computers with dual interfaces.
                if ((y == 0) && (amtwirelessif != y) && (z['MACAddress'] == '00-00-00-00-00-00')) { continue; } // On computers with only wireless, the wired interface will have a null MAC, skip it.
                if (y == 0) systemdefense++;
                x += '<br><h2>' + ((amtwirelessif == y)?"Interface sans fil":"Interface filaire") + '</h2>';
                x += TableStart();

                /*
                var lp = [], linkpolicy = MakeToArray(z['LinkPolicy']);
                for (var p in linkpolicy) {
                    var ap = linkpolicy[p];
                    if (ap == 1) lp.push("S0/AC");
                    if (ap == 14) lp.push("Sx/AC");
                    if (ap == 16) lp.push("S0/DC");
                    if (ap == 224) lp.push("Sx/DC");
                }
                x += TableEntry("Link state", (z['LinkIsUp'] == true?"Link is up":"Link is down") + ", available in " + lp.join(', '));
                */
                x += TableEntry("État du lien", (z['LinkIsUp'] == true?"Le lien est en place":"Le lien est en panne"));
                if (z['LinkPolicy']) {
                    z['LinkPolicy'] = MakeToArray(z['LinkPolicy']);
                    var linkPolicyStr = [];
                    for (var i in z['LinkPolicy']) {
                        if (z['LinkPolicy'][i] == 1) { linkPolicyStr.push("S0 / AC"); }
                        if (z['LinkPolicy'][i] == 14) { linkPolicyStr.push("Sx / AC"); }
                        if (z['LinkPolicy'][i] == 16) { linkPolicyStr.push("S0 / DC"); }
                        if (z['LinkPolicy'][i] == 224) { linkPolicyStr.push("Sx / DC"); }
                    }
                    if (linkPolicyStr.length == 0) { linkPolicyStr.push(''); }
                    x += TableEntry("Politique de lien", addLinkConditional((linkPolicyStr.length == 0) ? "Indisponible" : "Disponible en: " + linkPolicyStr.join(', '), 'showLinkPolicyDlg(' + y + ')', xxAccountAdminName));
                }
                if (z['MACAddress'] != '00-00-00-00-00-00') { x += TableEntry("Adresse Mac", z['MACAddress']); }

                // ###BEGIN###{Wireless}
                if ((amtwirelessif == y) && xxWireless && xxWireless['CIM_WiFiPortCapabilities'].response) {
                    // Start and state
                    x += TableEntry("Etat", addLinkConditional(xxWifiState[xxWireless['CIM_WiFiPort'].response['EnabledState']], 'showWifiStateDlg()', xxAccountAdminName));
        
                    /* This is not that useful
                    // Capabilities
                    var s = '', sc = xxWireless['CIM_WiFiPortCapabilities'].response, supportedTypes = sc['SupportedPortTypes'];
                    for (i in supportedTypes) { s += ", 802.11" + "abgn"[supportedTypes[i] - 70]; }
                    x += TableEntry("Capabilites", s.substring(2));
                    */

                    // Current radio state
                    s = xxWireless['CIM_WiFiEndpoint'].response['LANID'];
                    x += TableEntry("État de la radio", xxRadioState[xxWireless['CIM_WiFiEndpoint'].response['EnabledState']] + ", SSID: " + (s ? s : ('<i>' + "Aucun" + '</i>')));

                    // Current local profile synchronization
                    if (xxWireless['AMT_WiFiPortConfigurationService'] && xxWireless['AMT_WiFiPortConfigurationService'].response && (typeof xxWireless['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 'number')) {
                        x += TableEntry("Local WIFI Profile Sync", addLinkConditional(((xxWireless['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 1) ? "Activée" : "désactivé"), 'showWifiSyncDlg(' + y + ')', xxAccountAdminName));
                    }
                    // CSME UEFI Wifi profile sharing, check if it is enabled in boot setting and it is not null at AMT_WiFiPortConfigrationService
                    if (amtsysstate['AMT_BootCapabilities'].response['UEFIWiFiCoExistenceAndProfileShare'] != null && amtsysstate['AMT_BootCapabilities'].response['UEFIWiFiCoExistenceAndProfileShare'] == true
                        && xxWireless['AMT_WiFiPortConfigurationService'].response['UEFIWiFiProfileShareEnabled']!=null) {
                            x += TableEntry("UEFI WiFi CoEx Profile sharing", addLinkConditional(xxWireless['AMT_WiFiPortConfigurationService'].response['UEFIWiFiProfileShareEnabled']==1? "Activée":"désactivé", 'showUefiWifiCoExDlg()', xxAccountAdminName));
                     } else {
                        x += TableEntry("UEFI WiFi CoEx Profile sharing", "Unavailable");
                     }
                }
                // ###END###{Wireless}

                if (amtwirelessif != y) {
                    // Things that are specific to the wired interface
                    x += TableEntry("Répondre au ping", addLinkConditional(["désactivé", "Réponse ICMP", "Réponse RMCP", "Réponse ICMP et RMCP"][gs['PingResponseEnabled'] + (gs['RmcpPingResponseEnabled'] << 1)], 'showPingActionDlg()', xxAccountAdminName));
                    // ###BEGIN###{NetAuth}
                    // 802.1x
                    var netAuthProtocols = ['EAP-TLS', 'EAP-TTLS/MSCHAPv2', 'PEAPv0/EAP-MSCHAPv2', 'PEAPv1/EAP-GTC', 'EAP-FAST/MSCHAPv2', 'EAP-FAST/GTC', 'EAP-FAST/TLS'], netAuthStr = "désactivé";
                    if (amtsysstate['AMT_8021XProfile'].responses.Body['Enabled']) { netAuthStr = "Activée," + netAuthProtocols[amtsysstate['AMT_8021XProfile'].responses.Body['AuthenticationProtocol']]; }
                    x += TableEntry("802.1x", addLinkConditional(netAuthStr, 'editNetAuthProfile()', xxAccountAdminName));
                    // ###END###{NetAuth}
                    var ipStateString = z['DHCPEnabled'] == true ? "Automatique à l'aide du serveur DHCP" : "Adresse IP statique";
                    if (z['IpSyncEnabled'] == true) { ipStateString += ', IP sync with OS'; }
                    x += TableEntry("État IPv4", addLinkConditional(ipStateString, 'showIPSetupDlg()', xxAccountAdminName));
                }

                // Display IPv4 current settings
                x += TableEntry("Adresse IPv4", isIpAddress(z['IPAddress'],"Aucun"));
                if (isIpAddress(z['DefaultGateway'])) { x += TableEntry("Passerelle / masque IPv4", z['DefaultGateway'] + ' / ' + isIpAddress(z['SubnetMask'],"Aucun")); }
                
                var dns = z['PrimaryDNS'];
                if (isIpAddress(dns)) {
                    if (z['SecondaryDNS']) dns += ' / ' + z['SecondaryDNS'];
                    x += TableEntry("Serveur de nom de domaine IPv4", dns);
                }

                if ((amtsysstate['IPS_IPv6PortSettings'].status == 200) && (amtversion > 5)) {
                    // Check if IPv6 is enabled for this interface
                    var zz = amtsysstate['IPS_IPv6PortSettings'].responses[y];
                    var ipv6state = "désactivé", ipv6, ipv6manual, elementSettings = amtsysstate['CIM_ElementSettingData'].responses;
                    for (var i = 0; i < elementSettings.length; i++) {
                        if (elementSettings[i]['SettingData'] && elementSettings[i]['SettingData']['ReferenceParameters']['SelectorSet']['Selector']['Value'] == 'Intel(r) IPS IPv6 Settings ' + y) {
                            ipv6 = (elementSettings[i]['IsCurrent'] == 1);
                        }
                    }

                    // Check if manual addresses have been added
                    if (ipv6 == true) { 
                        ipv6manual = isIpAddress(zz['IPv6Address']) || isIpAddress(zz['DefaultRouter']) || isIpAddress(zz['PrimaryDNS']) || isIpAddress(zz['SecondaryDNS']);
                        ipv6state = (ipv6manual ? "Adresses activées, automatiques et manuelles" : "Activé, adresses automatiques");
                    }

                    // Display IPv6 current settings
                    x += TableEntry("État IPv6", addLinkConditional(ipv6state, 'showIPv6StateDlg(' + y + ',' + ipv6 + ')', xxAccountAdminName));
                    if (ipv6 == true) {
                        if (zz['CurrentAddressInfo'] && zz['CurrentAddressInfo'].length > 0) {
                            zz['CurrentAddressInfo'] = MakeToArray(zz['CurrentAddressInfo']); // Because our WSMAN stack does not know if this is a array, we need to make it an array if it contains 1 element.
                            ipv6addr = '';
                            for (var i = 0; i < zz['CurrentAddressInfo'].length; i++) { if (ipv6addr.length > 0) ipv6addr += ","; ipv6addr += zz['CurrentAddressInfo'][i].split(',')[0]; }
                            x += TableEntry("Adresse IPv6", addLink(ipv6addr, 'showIPv6AddrDlg(' + y + ',\"' + zz['CurrentAddressInfo'] + '\")'));
                        } else {
                            x += TableEntry("Adresse IPv6", "Aucun");
                        }
                        if (isIpAddress(zz['CurrentDefaultRouter'])) { x += TableEntry("Routeur par défaut IPv6", zz['CurrentDefaultRouter']); }
                        if (isIpAddress(zz['CurrentPrimaryDNS'])) {
                            var dns = zz['CurrentPrimaryDNS'];
                            if (isIpAddress(zz['CurrentSecondaryDNS'])) dns += ' / ' + zz['CurrentSecondaryDNS'];
                            x += TableEntry("Serveur de nom de domaine IPv6", dns);
                        }
                    }
                }

                x += TableEnd();
            }

            // Only do more WSMAN if we need it
            if ((urlvars['kvmonly'] != 1) && (fullscreenonly == false)) {
                // ###BEGIN###{Wireless}
                // If there is a wireless interface, get the data for it. If not, show that there is not.
                if (amtwirelessif != -1) { if ((amtFirstPull & 2) == 0) PullWireless(); }
                // ###END###{Wireless}
                QH('id_TableNetworkSettingsSpan', x);
                // ###END###{NetworkSettings}

                // ###BEGIN###{SystemDefense}
                // If in ACM mode and we have a wired interface, pull System Defense information
                if ((systemdefense == 1) && ((amtFirstPull & 4) == 0)) PullSystemDefense();
                // ###END###{SystemDefense}

                // ###BEGIN###{Storage}
                if (((amtFirstPull & 8) == 0) && (amtversion > 11 || ((amtversion == 11) && (amtversionmin > 5)))) { PullStorage(); }
                // ###END###{Storage}
            }

            if (currentView == 0) go(1, 1); // If we are at the loading screen, most to System Status screen
        }

        function isIpAddress(t, x) { return (t && t != null && t.length > 0 && t != '::' && t != '::0')?t:x; }

        function showLinkPolicyDlg(y) {
            if (xxdialogMode) return;
            var z = amtsysstate['AMT_EthernetPortSettings'].responses[y], s = '';
            s += '<label><input type=checkbox id=d11p1 value=1 ' + ((z['LinkPolicy'].indexOf(1) >= 0) ? 'checked' : '') + '>Available in S0/AC - Powered on & plugged in</label><br>';
            s += '<label><input type=checkbox id=d11p2 value=14 ' + ((z['LinkPolicy'].indexOf(14) >= 0) ? 'checked' : '') + '>Available in Sx/AC - Sleeping & plugged in</label><br>';
            s += '<label><input type=checkbox id=d11p3 value=16 ' + ((z['LinkPolicy'].indexOf(16) >= 0) ? 'checked' : '') + '>Available in S0/DC - Powered on & on battery</label><br>';
            s += '<label><input type=checkbox id=d11p4 value=224 ' + ((z['LinkPolicy'].indexOf(224) >= 0) ? 'checked' : '') + '>Available in Sx/DC - Sleeping & on battery</label><br>';
            setDialogMode(11, "Politique de lien", 3, showLinkPolicyDlgEx, s, y);
        }

        function showLinkPolicyDlgEx(b, y) {
            var x = Clone(amtsysstate['AMT_EthernetPortSettings'].responses[y]);
            if (x['DHCPEnabled']) {
                delete x['IPAddress'];
                delete x['SubnetMask'];
                delete x['DefaultGateway'];
                delete x['PrimaryDNS'];
                delete x['SecondaryDNS'];
            }
            x['LinkPolicy'] = [];
            if (Q('d11p1').checked) { x['LinkPolicy'].push(1); }
            if (Q('d11p2').checked) { x['LinkPolicy'].push(14); }
            if (Q('d11p3').checked) { x['LinkPolicy'].push(16); }
            if (Q('d11p4').checked) { x['LinkPolicy'].push(224); }
            amtstack.Put('AMT_EthernetPortSettings', x, showLinkPolicyDlgExDone, 0, 1, x);
        }

        function showLinkPolicyDlgExDone(stack, name, response, status) {
            if (status == 200) {
                amtsysstate = undefined;
                PullSystemStatus();
            } else {
                messagebox("Politique de lien", format("Impossible de définir une nouvelle stratégie de lien, erreur {0}", status));
            }
        }

        function showAuthCsme() {
            if (xxdialogMode) return;
            var x = '<div style=margin-top:8px>' + "Intel&reg; AMT supports authentic CSME feature, however MeshCommander cannot verify the authenticity yet." + '</div><hr style=margin-top:8px;margin-bottom:8px;height:2px;border-width:0;color:gray;background-color:gray />';
            x += addHtmlValue("FW Version", amtstack.amtauth.FWVersion);
            x += addHtmlValue("FQDN", amtstack.amtauth.FQDN ? amtstack.amtauth.FQDN : ('<i>' + "Aucun" + '</i>'));
            x += '<hr style=margin-top:8px;margin-bottom:8px;height:2px;border-width:0;color:gray;background-color:gray /><div style=max-height:200px;overflow-y:auto><table>';
            for (var i in amtstack.amtauth.Certificates) {
                var cert = amtstack.amtauth.Certificates[i];
                x += '<tr><td style=width:32px;vertical-align:top><img src=images-commander/cert1.png height=32 width=32 />';
                x += '<td style=padding-bottom:6px><b>' + EscapeHtml(cert.subject.getField('CN').value) + ((cert.xTrusted === true) ? ', <span style=color:#080>' + "De confiance" + '</span>' : '') + '</b><br />';
                if (cert.subject.getField('OU')) { x += EscapeHtml(cert.subject.getField('OU').value) + '<br />'; }
                // ###BEGIN###{FileSaver}
                x += amtstack.amtauth.CertificatesDer[i].length + " octets," + '<a style=cursor:pointer;color:blue onclick=downloadAuthCert(' + i + ')>' + "Télécharger" + '</a>';
                if (cert.xCrl) { x += '<br />' + "CRL " + cert.xCrl.length + " octets," + '<a style=cursor:pointer;color:blue onclick=downloadCertCrl(' + i + ')>' + "Télécharger" + '</a>'; }
                // ###END###{FileSaver}
                // ###BEGIN###{!FileSaver}
                x += amtstack.amtauth.CertificatesDer[i].length + " octets";
                if (cert.xCrl) { x += '<br />' + "CRL " + cert.xCrl.length + " octets"; }
                // ###END###{!FileSaver}
            }
            x += '</table><div>';
            setDialogMode(11, "Authentic CSME", 1, null, x);
        }

        // ###BEGIN###{FileSaver}
        function downloadCertCrl(h) {
            h = parseInt(h);
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(amtstack.amtauth.Certificates[h].xCrl), amtstack.amtauth.Certificates[h].subject.getField('CN').value + '.crl');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', amtstack.amtauth.Certificates[h].subject.getField('CN').value + '.crl');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, amtstack.amtauth.Certificates[h].xCrl, 'binary', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }

        function downloadAuthCert(h) {
            h = parseInt(h);
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(amtstack.amtauth.CertificatesDer[h]), amtstack.amtauth.Certificates[h].subject.getField('CN').value + '.cer');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', amtstack.amtauth.Certificates[h].subject.getField('CN').value + '.cer');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, amtstack.amtauth.CertificatesDer[h], 'binary', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

// ###BEGIN###{WsmanBrowser}
// ###BEGIN###{FileSaver}
        var IntelAmtEntireState;
        var IntelAmtEntireStateCalls;
        function saveEntireAmtState() {
            if (xxdialogMode) return;
            var n = '', d = new Date();
            if (amtsysstate) { n = '-' + amtsysstate['AMT_GeneralSettings'].response['HostName']; }
            n += '-' + d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);;
            idx_d19savestatefilename.value = 'amtstate' + n + '.json';
            setDialogMode(19, "Enregistrer l'intégralité de l'état Intel&reg; AMT", 3, saveEntireAmtStateOk);
        }

        function saveEntireAmtStateOk() {
            IntelAmtEntireState = { 'webappversion':version,'localtime':Date(),'utctime':new Date().toUTCString(),'isotime':new Date().toISOString() };
            QH('id_dialogMessage', 'Fetching entire state, please wait...');
            setDialogMode(1, "Enregistrer l'intégralité de l'état Intel&reg; AMT", 0, null);

            // Fetch everything!
            IntelAmtEntireStateCalls = 3;
            amtstack.BatchEnum(null, AllWsman, saveEntireAmtStateOk2, null, true);
            amtstack.GetAuditLog(saveEntireAmtStateOk3);
            amtstack.GetMessageLog(saveEntireAmtStateOk4);
        }

        function saveEntireAmtStateOk2(stack, name, responses, status) { IntelAmtEntireState['wsmanenums'] = responses; saveEntireAmtStateDone(); }
        function saveEntireAmtStateOk3(stack, messages) { IntelAmtEntireState['auditlog'] = messages; saveEntireAmtStateDone(); }
        function saveEntireAmtStateOk4(stack, messages) { IntelAmtEntireState['eventlog'] = messages; saveEntireAmtStateDone(); }

        function saveEntireAmtStateDone() {
            if (--IntelAmtEntireStateCalls != 0) return;
            setDialogMode();
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(JSON.stringify(IntelAmtEntireState, null, '  ').replace(/\n/g, '\r\n')), idx_d19savestatefilename.value);
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', idx_d19savestatefilename.value);
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, JSON.stringify(IntelAmtEntireState, null, '  ').replace(/\n/g, '\r\n'), function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
// ###END###{FileSaver}
// ###END###{WsmanBrowser}

// ###BEGIN###{Desktop-Settings}

        function showDesktopSettingsDlg() {
            if (xxdialogMode) return;
            var desktopSettings = amtsysstate['IPS_KVMRedirectionSettingData'].response;
            var x = '<div style=text-align:left>';
            x += '<div style=height:26px;margin-top:4px><select id=subddisplay style=float:right;width:200px><option value=0>' + "Affichage principal" + '</option><option value=1>' + "Affichage secondaire" + '</option>';
            if (amtversion > 9) { x += '<option value=2>' + "3e affichage" + '</option>'; }
            x += '</select><div style=padding-top:4px>' + "Affichage par défaut" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=subsessiontimeout style=float:right;width:200px maxlength=5 onkeypress="return numbersOnly(event)"><div style=padding-top:4px>' + "Délai d'expiration de la session (minutes)" + '</div></div>';
            if (desktopSettings['OptInPolicy'] == true) { x += '<div style=height:26px;margin-top:4px><input id=suboptintimeout style=float:right;width:200px maxlength=5 onkeypress="return numbersOnly(event)"><div style=padding-top:4px>' + "Délai d'expiration (secondes)" + '</div></div>'; }
            x += '<div style=height:26px;margin-top:4px><select id=subdlegacy style=float:right;width:200px onchange=showDesktopSettingsDlgUpdate()><option value=0>' + "Désactivé, recommandé" + '</option><option value=1>' + "Visionneuses KVM héritées activées" + '</option></select><div style=padding-top:4px>' + "Port 5900" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=subspassx><input id=subspass type=password autocomplete=off style=float:right;width:200px maxlength=8 onkeyup=showDesktopSettingsDlgUpdate()><div style=padding-top:4px>' + "Mot de passe 5900 (8 caractères)" + '</div></div>';
            if ((amtversion > 9) && (amtsysstate['IPS_ScreenConfigurationService'] != null)) { x += '<div style=height:26px;margin-top:4px><select id=subsb style=float:right;width:200px onchange=showDesktopSettingsDlgUpdate()><option value=0>' + "désactivé" + '</option><option value=1>' + "Activée" + '</option></select><div style=padding-top:4px title="' + "Cette fonctionnalité n'est pas souvent prise en charge" + '">' + "Masquage d'écran" + '</div></div>'; }
            x += '</div>';
            setDialogMode(11, "Paramètres du bureau à distance", 3, showDesktopSettingsDlgOk, x);
            Q('subddisplay').value = desktopSettings['DefaultScreen'];
            Q('subsessiontimeout').value = desktopSettings['SessionTimeout'];
            if (desktopSettings['OptInPolicy'] == true) { Q('suboptintimeout').value = desktopSettings['OptInPolicyTimeout']; }
            Q('subdlegacy').value = ((desktopSettings['Is5900PortEnabled'] == true) ? 1 : 0);
            if ((amtversion > 9) && (amtsysstate['IPS_ScreenConfigurationService'] != null)) { Q('subsb').value = amtsysstate['IPS_ScreenConfigurationService'].response['EnabledState']; }
            showDesktopSettingsDlgUpdate();
        }

        function showDesktopSettingsDlgUpdate() {
            QV('subspassx', (Q('subdlegacy').value == 1));
            var ok = ((Q('subdlegacy').value == 0) || (Q('subspass').value.length == 8) || (Q('subspass').value.length == 0)) && (Q('subsessiontimeout').value.length > 0);
            if ((amtsysstate['IPS_KVMRedirectionSettingData'].response['OptInPolicy'] == true) && (Q('suboptintimeout').value.length == 0)) { ok = false; }
            QE('idx_dlgOkButton', ok);
        }

        function showDesktopSettingsDlgOk() {
            var x = Clone(amtsysstate['IPS_KVMRedirectionSettingData'].response);
            x['DefaultScreen'] = Q('subddisplay').value
            x['SessionTimeout'] = Q('subsessiontimeout').value;
            x['Is5900PortEnabled'] = (Q('subdlegacy').value == 1);
            if (x['OptInPolicy'] == true) { x['OptInPolicyTimeout'] = Q('suboptintimeout').value; }
            if (x['Is5900PortEnabled'] == true) { x['RFBPassword'] = Q('subspass').value; }
            amtstack.Put('IPS_KVMRedirectionSettingData', x, showDesktopSettingsDlgOk2);

            // Screen blanking
            var y = Clone(amtsysstate['IPS_ScreenConfigurationService'].response);
            y['EnabledState'] = parseInt(Q('subsb').value);
            amtstack.Put('IPS_ScreenConfigurationService', y, showDesktopSettingsDlgOk3);
        }

        function showDesktopSettingsDlgOk2(stack, name, responses, status) {
            if (status == 200) PullSystemStatus(); else messagebox("Paramètres du bureau à distance", format("Erreur {0}, impossible de définir des valeurs.", status));
        }

        function showDesktopSettingsDlgOk3(stack, name, response, status) {
            if (status != 200) { messagebox("Erreur", format("La suppression de l'écran n'a pas pu être définie, la suppression peut ne pas être prise en charge sur ce système ({0}).", status)); return; }
            amtstack.Get('IPS_ScreenConfigurationService', function (stack, name, response, status) {
                if (status == 200) { amtsysstate['IPS_ScreenConfigurationService'].response = response.Body; updateSystemStatus(); }
            }, 0, 1);
        }

// ###END###{Desktop-Settings}

// ###BEGIN###{EventLog}

        //
        // EVENT LOG PANEL
        //

        function PullEventLog(button) {
            if (button == 1 && xxdialogMode) return;
            amtFirstPull |= 16;
            amtstack.Enum('AMT_MessageLog', processMessageLog0);
            amtstack.GetMessageLog(processMessageLog1);
        }

        var processMessageLog0responses = null;
        function processMessageLog0(stack, name, responses, status) {
            if (status != 200) return;
            if (status) QV('go6', true); // Show event log left panel option
            if (responses) processMessageLog0responses = responses;
            var fr = '', x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px>';
            if (processMessageLog0responses != null) { fr = ((processMessageLog0responses[0]['IsFrozen'] == true) ? AddButton("Annuler le gel du journal", 'FreezeLog(0)') : AddButton("Figer le journal", 'FreezeLog(1)')); }

            // ###BEGIN###{!FileSaver}
            x += TableEnd('<div style=float:right><input id=eventFilter placeholder="' + "Filtre" + '" style=margin:4px onkeyup=eventFilter()>&nbsp;</div><div>&nbsp;' + AddRefreshButton('PullEventLog(1)') + AddButton("Effacer le journal", 'ClearLog()') + fr);
            // ###END###{!FileSaver}
            // ###BEGIN###{FileSaver}
            x += TableEnd('<div style=float:right><input id=eventFilter placeholder="' + "Filtre" + '" style=margin:4px onkeyup=eventFilter()>&nbsp;</div><div>&nbsp;' + AddRefreshButton('PullEventLog(1)') + AddButton("Effacer le journal", 'ClearLog()') + AddButton("Sauver...", 'SaveEventLog()') + fr);
            // ###END###{FileSaver}
            QH('id_TableEventLog', x + '<br>');
        }

        // ###BEGIN###{FileSaver}
        function SaveEventLog() {
            if (xxdialogMode || eventmessages == null) return;
            SaveJsonFile('IntelAmtEventlog', 'events', 'Intel AMT Event Log', eventmessages);
        }
        // ###END###{FileSaver}

        var eventmessages = null;
        function processMessageLog1(stack, messages) {
            eventmessages = messages;
            var i, y = 0, x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td width=80px><p><td><td><td>';
            x += '<tr><td class=r1 style=width:90px><b>&nbsp;&nbsp;Event</b><td class=r1 style=width:110px><b>Time</b><td class=r1 style=width:160px><b>' + "La source" + '</b><td class=r1><b>' + "La description" + '</b>';
            for (i in messages) {
                y++;
                var icon = 1, m = messages[i];
                if (m['EventSeverity'] >= 8) { icon = 2; } if (m['EventSeverity'] >= 16) { icon = 3; }
                x += '<tr id=xamtevent' + i + ' class=r3 onclick=showEventDetails(' + i + ')><td class=r1><p><div class=icon' + icon + ' style=display:block;float:left;margin-left:5px;margin-right:5px></div>' + (parseInt(i) + 1) + '<td class=r1 title="' + m['Time'].toLocaleString() + '">' + m['Time'].toLocaleDateString('en', { year: 'numeric', month: '2-digit', day: 'numeric' }) + '<br>' + m['Time'].toLocaleTimeString('en', { hour:'2-digit', minute:'2-digit', second:'2-digit' }) + '<td class=r1>' + m['EntityStr'].replace('(r)', '&reg;') + '<td class=r1>' + m['Desc'];
            }
            x += TableEnd(y == 0 ? '&nbsp;' : '');
            QH('id_TableEventLog2', x + '<br>');
            processMessageLog0();
        }

        function FreezeLog(x) { if (!xxdialogMode) { amtstack.AMT_MessageLog_FreezeLog(x, function () { amtstack.Enum('AMT_MessageLog', processMessageLog0); }) } }
        function ClearLog(x) { if (!xxdialogMode) { QH('id_dialogMessage', "Effacer le journal des événements?"); setDialogMode(1, "Journal des événements", 3, ClearLogEx); } }
        function ClearLogEx() { amtstack.AMT_MessageLog_ClearLog(function (stack, name, responses, status) { if (status != 200) messagebox("Journal des événements", "Impossible d'effacer, erreur: " + status); else PullEventLog(); }) }

        function showEventDetails(h) {
            if (xxdialogMode) return;
            var m = eventmessages[h];
            var x = '<div style=text-align:left>';
            x += addHtmlValue("Temps", m['Time'].toLocaleString());
            x += addHtmlValue("La source", m['EntityStr'].replace('(r)', '&reg;'));
            x += addHtmlValue("La description", m['Desc']);
            x += MoreStart();
            x += addHtmlValue("Adresse de l'appareil", m['DeviceAddress']);
            x += addHtmlValue("Entité", m['Entity']);
            x += addHtmlValue("Instance d'entité", m['EntityInstance']);
            var e = '';
            for (var i in m['EventData']) { if (e.length > 0) e +=','; e += m['EventData'][i]; }
            x += addHtmlValue("Les données", e);
            x += addHtmlValue("Décalage", m['EventOffset']);
            x += addHtmlValue("Type de capteur", m['EventSensorType']);
            x += addHtmlValue("Gravité", m['EventSeverity']);
            x += addHtmlValue("Type de Source", m['EventSourceType']);
            x += addHtmlValue("Type", m['EventType']);
            x += addHtmlValue("Numéro de capteur", m['SensorNumber']);
            x += MoreEnd();
            x += '</div>';
            messagebox(format("Détails de l'événement # {0}", h + 1), x);
        }

        function eventFilter() {
            var filter = Q('eventFilter').value.toLowerCase();
            for (var w in eventmessages) { QV('xamtevent' + w, filter == '' || eventmessages[w]['Desc'].toLowerCase().indexOf(filter) >= 0 || eventmessages[w]['EntityStr'].toLowerCase().indexOf(filter) >= 0); }
        }

// ###END###{EventLog}

// ###BEGIN###{EventSubscriptions}

        //
        // EVENT SUBSCRIPTION PANEL
        //

        var subscriptionsFilters = null; // List of event filters
        var subscriptionsListeners = null; // List of subscribers

        function PullEventSubscriptions() {
            if (subscriptionsFilters == null) { amtstack.Enum('CIM_FilterCollection', processEventSubscriptions0); }
            amtstack.BatchEnum(null, ['CIM_ListenerDestination', 'CIM_FilterCollectionSubscription'], processEventSubscriptions1);
        }

        function processEventSubscriptions0(stack, name, responses, status) {
            if (status == 408 || status == 400) return;
            if (status && errcheck(status, stack)) return;
            subscriptionsFilters = responses;
        }

        function processEventSubscriptions1(stack, name, responses, status) {
            if (status == 408 || status == 400) return;
            if (status && errcheck(status, stack)) return;
            if (status) QV('go22', true); // Show event subscription left panel option
            if (responses) subscriptionsListeners = responses;
            var c= 0, x = TableStart2() + '<tr><td class=r1 style=padding-left:15px><br>' + "Gérez les abonnés aux événements." + '<br><br>';
            for (var i in subscriptionsListeners['CIM_ListenerDestination']['responses']) {
                var f = subscriptionsListeners['CIM_FilterCollectionSubscription']['responses'][i]['Filter']['ReferenceParameters']['SelectorSet']['Selector']['Value'].replace('(r)', '&reg;');
                var r = subscriptionsListeners['CIM_ListenerDestination']['responses'][i];
                x += '<div class=itemBar onclick="showSubscriptionDetails(' + i + ')"><div style=float:right></div><div style=padding-top:3px;overflow-x:hidden title="' + f + ' - ' + r['Destination'] + '"><b>' + f + '</b> - ' + r['Destination'] + '</div><div style=padding-top:3px></div></div>';
                c++;
            }
            if (c == 0) x += ('<div style=padding-left:15px><br><i>' + "Aucun abonnement trouvé." + '</i></div><br>');
            var y = '<div>&nbsp;' + AddRefreshButton('PullEventSubscriptions()');
            if (xxAccountAdminName) y += AddButton("Nouvel abonnement", 'newSubscriptionButton()');
            x += '<br><td class=r1>' + TableEnd(y + '</div>');
            QH('id_TableEventSubscriptions', x);
        }

        var subscriptionDeliveryModes = { 2:"Pousser", 3:"Poussez avec ACK", 4:"Événements", 5:"Tirer" };
        function showSubscriptionDetails(h) {
            if (xxdialogMode) return;
            var f = subscriptionsListeners['CIM_FilterCollectionSubscription']['responses'][h]['Filter']['ReferenceParameters']['SelectorSet']['Selector']['Value'].replace('(r)', '&reg;');
            var r = subscriptionsListeners['CIM_ListenerDestination']['responses'][h];
            var x = '<div style=text-align:left>';
            x += addHtmlValue("Destination", r['Destination']);
            x += addHtmlValue("Filtre", f);
            x += addHtmlValue("Mode de livraison", subscriptionDeliveryModes[r['DeliveryMode']]);
            x += '</div>';
            setDialogMode(11, "Abonnement" + (h + 1), xxAccountAdminName?5:1, deleteSubscriptionButton, x, h);
        }

        function deleteSubscriptionButton(button, h) {
            if (button != 2) return;
            var name = subscriptionsListeners['CIM_ListenerDestination']['responses'][h]['Name'];
            var filter = subscriptionsListeners['CIM_FilterCollectionSubscription']['responses'][h]['Filter']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
            amtstack.UnSubscribe('CIM_FilterCollectionSubscription', PullEventSubscriptions, null, 1, {'Filter':'<a:EndpointReference><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_FilterCollection</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + filter + '</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference>', 'Handler':'<a:EndpointReference><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ListenerDestinationWSManagement</w:ResourceURI><w:SelectorSet><w:Selector Name="CreationClassName">CIM_ListenerDestinationWSMAN</w:Selector><w:Selector Name="Name">' + name + '</w:Selector><w:Selector Name="SystemCreationClassName">CIM_ComputerSystem</w:Selector><w:Selector Name="SystemName">Intel(r) AMT</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference>'});
        }

        function newSubscriptionButton() {
            if (xxdialogMode || (subscriptionsFilters == null)) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><select id=subtype style=float:right;width:260px><option value=Push>' + "Pousser" + '</option><option value=PushWithAck>' + "Poussez avec ACK" + '</option></select><div style=padding-top:4px>' + "Type" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=subfilter style=float:right;width:260px>';
            for (var i in subscriptionsFilters) { x += '<option value="' + subscriptionsFilters[i]['InstanceID'] + '">' + subscriptionsFilters[i]['CollectionName'].substring(13) + '</option>'; }
            x += '</select><div style=padding-top:4px>' + "Filtre" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=suburl style=float:right;width:260px maxlength=253 onkeyup=newSubscriptionUpdate() value="http://"><div style=padding-top:4px>' + "URL" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=subauth style=float:right;width:260px onchange=newSubscriptionUpdate()><option value=0>' + "Aucun" + '</option><option value=1>' + "Digérer" + '</option></select><div style=padding-top:4px>' + "Authentification" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=subxuser><input id=subuser style=float:right;width:260px maxlength=32 onkeyup=newSubscriptionUpdate()><div style=padding-top:4px>' + "Nom d'utilisateur" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=subxpass><input id=subpass style=float:right;width:260px maxlength=32 onkeyup=newSubscriptionUpdate()><div style=padding-top:4px>' + "Mot de passe" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=subargs style=float:right;width:260px maxlength=128><div style=padding-top:4px>' + "Arguments" + '</div></div>';
            setDialogMode(11, "Ajouter un abonnement à un événement", 3, newSubscriptionButtonOk, x);
            newSubscriptionUpdate();
        }

        function newSubscriptionUpdate() {
            QE('idx_dlgOkButton', ((Q('suburl').value.length > 0) && (Q('suburl').value.startsWith('http://')) && ((Q('subauth').value == 0) || ((Q('subuser').value.length > 0) && (Q('subpass').value.length > 0)))));
            QV('subxuser', Q('subauth').value == 1);
            QV('subxpass', Q('subauth').value == 1);
        }

        function newSubscriptionButtonOk() {
            var user = (Q('subuser').value.length == 0)?undefined:Q('subuser').value, pass = (Q('subpass').value.length == 0)?undefined:Q('subpass').value;
            amtstack.Subscribe('CIM_FilterCollection', Q('subtype').value, Q('suburl').value, newSubscriptionButtonOk2, null, 1, { 'InstanceID' : Q('subfilter').value }, (Q('subargs').value.length > 0)?Q('subargs').value:null, user, pass);
        }

        function newSubscriptionButtonOk2(stack, name, responses, status) {
            if (status == 200) { PullEventSubscriptions(); }
        }

// ###END###{EventSubscriptions}

// ###BEGIN###{AuditLog}

        //
        // AUDIT LOG PANEL
        //

        function PullAuditLog(button) {
            if (button == 1 && xxdialogMode) return;
            amtFirstPull |= 32;
            amtstack.Enum('AMT_AuditLog', processAuditLog0);
        }

        var auditLog = null;
        var auditLogEnabledStates = ["Inconnue", "Autre", "Activée", "désactivé", "Éteindre", "N'est pas applicable", "Activé mais hors ligne", "En test", "Différé", "Au repos", "Départ"];

        function processAuditLog0(stack, name, responses, status) {
            if (status == 200) {
                QV('go15', true); // Show audit log left panel option

                var r = responses[0]['AuditState'];
                var auditstate = (r & 0x01) ? "désactivé" : "Activée";
                if (r & 0x02) auditstate += ", Fermé à clé";
                if (r & 0x04) auditstate += ", Presque plein";
                if (r & 0x08) auditstate += ", Plein";
                if (r & 0x10) auditstate += ", NoKey";

                var x = '<h1>' + "Paramètres du journal d'audit" + '</h1>' + TableStart();
                x += TableEntry("Etat", auditstate);
                x += TableEntry("Espace de rangement", responses[0]['CurrentNumberOfRecords'] + " enregistrement (s)," + responses[0]['PercentageFree'] + "% gratuit");
                x += TableEntry("Écraser la politique", ((responses[0]['OverwritePolicy'] == 2) ? "S'enveloppe lorsqu'il est plein" : "N'écrase jamais"));
                x += TableEnd();
                QH('id_TableAuditLog1', x);

                amtstack.GetAuditLog(processAuditLog1);
            }
        }

        function processAuditLog1(stack, messages) {
            auditLog = messages;
            var i, x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px>';
            // ###BEGIN###{!FileSaver}
            x += TableEnd('<div style=float:right><input id=auditFilter placeholder="' + "Filtre" + '" style=margin:4px onkeyup=auditFilter()>&nbsp;</div><div> ' + AddRefreshButton('PullAuditLog(1)') + AddButton("Effacer le journal", 'ClearAuditLog()') /* + AddButton("Settings...", 'ShowAuditLogSettings()')*/) + '<br>';
            // ###END###{!FileSaver}
            // ###BEGIN###{FileSaver}
            x += TableEnd('<div style=float:right><input id=auditFilter placeholder="' + "Filtre" + '" style=margin:4px onkeyup=auditFilter()>&nbsp;</div><div> ' + AddRefreshButton('PullAuditLog(1)') + AddButton("Sauver...", 'SaveAuditLog()') + AddButton("Effacer le journal", 'ClearAuditLog()') /* + AddButton("Settings...", 'ShowAuditLogSettings()')*/) + '<br>';
            // ###END###{FileSaver}
            if (messages.length == 0) {
                x = "Aucun événement de journal d'audit trouvé.";
            } else {
                var y = 0;
                x += '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td width=80px><p><td><td><td>';
                x += '<tr><td class=r1 style=width:110px>&nbsp;&nbsp;<b>' + "Temps" + '</b><td class=r1 style=width:260px><b>' + "Initiateur" + '</b><td class=r1><b>Action</b>';
                for (i in messages) {
                    var m = messages[i], description = m['AuditApp'], initiator = m['Initiator'];
                    y++;
                    var addr = '';
                    if (m['NetAddress'].length > 0) addr = m['NetAddress'].replace('0000:0000:0000:0000:0000:0000:0000:0001','::1');
                    if (m['Event']) description += "," + m['Event'];
                    if (m['ExStr'] != null) description += "," + m['ExStr'];
                    if (initiator != '' && addr != '') initiator += ",";
                    x += '<tr id=xamtaudit' + i + ' class=r3 onclick=showAuditDetails(' + i + ')><td class=r1 title="' + m['Time'].toLocaleString() + '">&nbsp;&nbsp;' + m['Time'].toLocaleDateString('en', { year: 'numeric', month: '2-digit', day: 'numeric' }) + '<br>&nbsp;&nbsp;' + m['Time'].toLocaleTimeString('en', { hour:'2-digit', minute:'2-digit', second:'2-digit' }) + '<td class=r1>' + initiator + addr + '<td class=r1>' + description;
                }
                x += TableEnd(y == 0 ? '&nbsp;' : '') + '<br>';
            }
            QH('id_TableAuditLog2', x);
        }

        function auditFilter() {
            var filter = Q('auditFilter').value.toLowerCase();
            for (var w in auditLog) { QV('xamtaudit' + w, filter == '' || JSON.stringify(auditLog[w]).toLowerCase().indexOf(filter) >= 0); }
        }

        // ###BEGIN###{FileSaver}
        function SaveAuditLog() {
            if (xxdialogMode || auditLog == null) return;
            SaveJsonFile('IntelAmtAuditlog', 'auditevents', "Journal d'audit Intel AMT", auditLog);
        }
        // ###END###{FileSaver}

        function ClearAuditLog(x) { QH('id_dialogMessage', "Effacer le journal d'audit?"); setDialogMode(1, "Journal d'audit", 3, ClearAuditLogEx); }
        function ClearAuditLogEx() {
            //amtstack.AMT_AuditLog_ClearLog(function () { PullAuditLog(); })
            var handle = amtstack.AMT_AuditLog_SetAuditLock(1,0, handle, function() { amtstack.AMT_AuditLog_ClearLog(function () { amtstack.AMT_AuditLog_SetAuditLock(0, 2, handle, function () { setTimeout(PullAuditLog,1000);}); }); });         
        }

        function ShowAuditLogSettings() {
            if (xxdialogMode) return;
            amtstack.AMT_AuditLog_RequestStateChange(2, 0, AuditLogSettingsCompleted); // Enable
        }

        function AuditLogSettingsCompleted(stack, name, responses, status) {
            if (status == 200) PullAuditLog(); else messagebox("Journal d'audit", "Erreur: " + status);
        }

        function showAuditDetails(h) {
            if (xxdialogMode) return;
            var i, m = auditLog[h], x = '<div style=text-align:left>';
            x += addHtmlValue("Temps", m['Time'].toLocaleString());
            if (m['Initiator'] != '') x += addHtmlValue("Initiateur", m['Initiator']);
            if (m['NetAddress'] != '') x += addHtmlValue("Adresse", m['NetAddress']);
            x += addHtmlValue("Application", m['AuditApp']);
            x += addHtmlValue("un événement", m['Event']);
            if (m['ExStr'] != null) {
                x += addHtmlValue("Données étendues", m['ExStr']);
            } else if (m['Ex'].length > 0) {
                var e = '';
                for (i in m['Ex']) { if (e.length > 0) e += ','; e += m['Ex'].charCodeAt(i); }
                if (e != '') x += addHtmlValue("Valeurs de données", e);
                if (m['Ex'].length > 2 && ReadShort(m['Ex'], 0) == (m['Ex'].length - 2)) x += addHtmlValue("Chaîne de données", m['Ex'].substring(2));
            }
            x += '</div>';
            messagebox("Événement d'audit #" + (h + 1) + " Détails", x);
        }

// ###END###{AuditLog}

// ###BEGIN###{Certificates}

        //
        // Certificates
        //

        var xxCertificates = null;
        var xxCertPrivateKeys = null;
        var xxTlsSettings = null;
        var xxTlsCurrentCert = null;
        var xxTLSCredentialContext = null;
        var xxCaPrivateKey = null;
        var xxCaSubjectAttributes = null;

        function PullCertificates() {
            // We only deal with certificates starting with Intel AMT 6 and beyond
            amtstack.BatchEnum(null, ['AMT_PublicKeyCertificate', 'AMT_PublicPrivateKeyPair', 'AMT_TLSSettingData', 'AMT_TLSCredentialContext'], processCerts1);
        }

        function processCerts1(stack, name, responses, status) {
            if ((status == 400) || errcheck(status, stack)) return;
            QV('go16', true); // Security Settings
            xxCertificates = responses['AMT_PublicKeyCertificate'].responses;
            xxCertPrivateKeys = responses['AMT_PublicPrivateKeyPair'].responses;
            xxTlsSettings = responses['AMT_TLSSettingData'].responses;
            xxTLSCredentialContext = responses['AMT_TLSCredentialContext'].responses;

            // Select the current TLS certificate in the drop down box
            xxTlsCurrentCert = null;
            if (xxTLSCredentialContext.length > 0) {
                var certInstanceId = xxTLSCredentialContext[0]['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
                for (var i in xxCertificates) { if (xxCertificates[i]['InstanceID'] == certInstanceId) { xxTlsCurrentCert = i; } }
            }

            // ###BEGIN###{Mode-NodeWebkit}
            try { if ((currentcomputer['tls'] == 0) && (xxTlsSettings[0]['MutualAuthentication'] !== true)) { QV('tlsNotification4', true); } } catch (ex) { console.log(ex); }
            // ###END###{Mode-NodeWebkit}

            // Setup the certificates
            for (var i in xxCertificates) {
                xxCertificates[i].TrustedRootCertficate = (xxCertificates[i]['TrustedRootCertficate'] == true);
                xxCertificates[i].X509Certificate = window.atob(xxCertificates[i]['X509Certificate']);
                xxCertificates[i].XIssuer = parseCertName(xxCertificates[i]['Issuer']);
                xxCertificates[i].XSubject = parseCertName(xxCertificates[i]['Subject']);
            }
            amtcert_linkCertPrivateKey(xxCertificates, xxCertPrivateKeys); // This links all certificates and private keys

            updateCertificates();
        }

        function parseCertName(x) {
            var j, r = {}, xx = x.split(',');
            for (var i in xx) { j = xx[i].indexOf('='); r[xx[i].substring(0, j)] = xx[i].substring(j + 1); }
            return r;
        }

        function getTlsSecurityState(x) {
            if (xxTlsSettings[x]['Enabled'] == false) return "désactivé";
            var r = ((xxTlsSettings[x]['MutualAuthentication'] == true) ? "TLS d'authentification mutuelle" : "TLS d'authentification de serveur") + ((xxTlsSettings[x]['AcceptNonSecureConnections'] == true) ? " et non TLS" : '');
            if ((xxTlsSettings[x]['MutualAuthentication'] == true) && (xxTlsSettings[x]['TrustedCN'])) {
                var trustedCn = MakeToArray(xxTlsSettings[x]['TrustedCN']);
                if (trustedCn.length > 0) { r += ', ' + ((trustedCn.length > 1) ? 'Trusted names' : 'Trusted name') + ': ' + trustedCn.join(', ') + '.'; }
            }
            return r;
        }

        function updateCertificates() {
            if (xxCertificates == null) return;

            // Figure out what index is local & remote
            var localNdx = ((xxTlsSettings[0]['InstanceID'] == 'Intel(r) AMT LMS TLS Settings')) ? 0 : 1, remoteNdx = (1 - localNdx);

            // General settings
            var x = TableStart();
            x += TableEntry("Sécurité TLS à distance", addLinkConditional(getTlsSecurityState(remoteNdx), 'showSetTlsSecurityDlg()', xxAccountAdminName));
            x += TableEntry("Sécurité TLS locale", addLinkConditional(getTlsSecurityState(localNdx), 'showSetTlsSecurityDlg()', xxAccountAdminName));
            x += TableEnd();
            x += '<br>' + TableStart2() + '<tr><td class=r1 style=padding-left:15px><br>' + "Gérez les certificats Intel&reg; AMT pour cet ordinateur." + '<br><br>';
            if (xxCertificates.length == 0 && xxCertPrivateKeys.length == 0) {
                x += '<div style=padding-left:15px><br><i>' + "Aucun certificat trouvé." + '</i></div><br>';
            } else {
                for (var i in xxCertificates) {
                    var desc = '';
                    if (xxCertificates[i].TrustedRootCertficate) desc = ", Racine de confiance";
                    if (xxCertificates[i].XPrivateKey) desc = ", Clé privée";
                    if (i == xxTlsCurrentCert) desc += ", TLS cert";
                    x += '<div class=itemBar onclick=showCertDetails(' + i + ')><div style=padding-top:3px><b>' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</b><i>' + desc + '</i></div></div>';
                }
                for (var i in xxCertPrivateKeys) {
                    if (!xxCertPrivateKeys[i].XCert) {
                        x += '<div class=itemBar onclick=showKeyPairDetails(' + i + ')><div style=padding-top:3px><i>' + "Paire de clés privées non affectées #" + i + '</i></div></div>';
                    }
                }
            }
            var buttons = AddRefreshButton('PullCertificates()');
            if (xxAccountAdminName) { buttons += (AddButton("Ajouter un certificat ...", 'addCertButton()') + AddButton("Délivrer un certificat ...", 'issueCertButton()')); }
            x += '<br><td class=r1>' + TableEnd(buttons);
            QH('id_TableCerts', x);
        }

        function showKeyPairDetails(h) {
            var x = "Il s'agit d'une paire de clés de certificat public / privé qui n'appartient à aucun certificat. Cette entrée doit être temporaire.";
            setDialogMode(11, "Paire de clés #" + h, 5, function (b) { if (b == 2) { amtstack.Delete('AMT_PublicPrivateKeyPair', { 'InstanceID': xxCertPrivateKeys[h]['InstanceID'] }, PullCertificates, 0, 1); } }, x);
        }

        var xxCertSubjectNames = { 'CN': "Nom commun", 'O': "Organisation", 'OU': "Unité organisationnelle", 'S': "État / Province", 'ST': "État / Province", 'L': "Localité", 'C': "Pays", 'SN': "Nom de famille", 'GN': "Prénom" };
        function showCertDetails(h) {
            if (xxdialogMode) return;
            var c = xxCertificates[h], x = '<br>';
            // ###BEGIN###{FileSaver}
            x += addHtmlValue("Certificat", c.X509Certificate.length + " octets," + '<a style=cursor:pointer;color:blue onclick=downloadCert(' + h + ')>' + "Télécharger" + '</a>');
            // ###END###{FileSaver}
            // ###BEGIN###{!FileSaver}
            x += addHtmlValue("Certificat", c.X509Certificate.length + " octets");
            // ###END###{!FileSaver}
            x += addHtmlValue("Racine de confiance", c.TrustedRootCertficate ? "Oui" : "Non");
            if (c.TrustedRootCertficate == false && c.XPrivateKey) { x += addHtmlValue("Clé privée", "Présent"); }

            // Show certificate usages
            /*
            y = [];
            if (extKeyUsage != null) {
                if (extKeyUsage.clientAuth == true) { y.push("TLS&nbsp;Client"); }
                if (extKeyUsage.codeSigning == true) { y.push("Code&nbsp;Signing"); }
                if (extKeyUsage.emailProtection == true) { y.push("EMail"); }
                if (extKeyUsage.serverAuth == true) { y.push("TLS&nbsp;Server"); }
                if (extKeyUsage["2.16.840.1.113741.1.2.1"] == true) { y.push("Intel&reg;&nbsp;AMT Console"); }
                if (extKeyUsage["2.16.840.1.113741.1.2.2"] == true) { y.push("Intel&reg;&nbsp;AMT Agent"); }
                if (extKeyUsage["2.16.840.1.113741.1.2.3"] == true) { y.push("Intel&reg;&nbsp;AMT Activation"); }
                if (extKeyUsage.timeStamping == true) { y.push("Time&nbsp;Stamping"); }
                if (y.length > 0) { x += addHtmlValueNoTitle("Certificate Usage", y.join(', ') + '.') + '<br clear=all />'; }
            }
            */

            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Objet du certificat" + '</i></div><br>';
            for (var i in c.XSubject) { if (c.XSubject[i]) { x += addHtmlValue(xxCertSubjectNames[i] ? xxCertSubjectNames[i] : i, EscapeHtml(c.XSubject[i])); } }
            // x += addHtmlValueNoTitle("Fingerprint", c.fingerprint.substring(0,29) + '<br />' + c.fingerprint.substring(30)); // TODO: Parse the certificate using Forge and get the fingerprint
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificat d'émetteur" + '</i></div><br>';
            for (var i in c.XIssuer) { if (c.XIssuer[i]) { x += addHtmlValue(xxCertSubjectNames[i] ? xxCertSubjectNames[i] : i, EscapeHtml(c.XIssuer[i])); } }
            setDialogMode(11, "Certificat -" + EscapeHtml(c.XSubject['CN']), 5, function (b) {
                if (b == 2) {
                    // If there is a private key, delete it.
                    if (xxCertificates[h].XPrivateKey) amtstack.Delete('AMT_PublicPrivateKeyPair', { 'InstanceID': xxCertificates[h].XPrivateKey['InstanceID'] }, function () { }, 0, 1);
                    // Delete the certificate
                    amtstack.Delete('AMT_PublicKeyCertificate', xxCertificates[h], certificateRemoved, 0, 1);
                }
            }, x);
        }

        // ###BEGIN###{FileSaver}
        function downloadCert(h) { 
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(xxCertificates[h].X509Certificate), xxCertificates[h].XSubject['CN'] + '.cer');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', xxCertificates[h].XSubject['CN'] + '.cer');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, xxCertificates[h].X509Certificate, 'binary', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        function cert_FileSelectHandler(e) {
            haltEvent(e);
            if (e.dataTransfer.files.length == 1) {
                if (e.dataTransfer.files[0].name.toLowerCase().endsWith('.p12')) {
                    issueCertButton(e.dataTransfer.files);
                } else {
                    addCertButton(e.dataTransfer.files);
                }
            }
        }

        var xxDragDropCertFiles = null;
        function addCertButton(files) {
            if (xxdialogMode || !xxAccountAdminName) return;
            var x = '<div style=height:10px></div>', op0 = '', op2 = '';
            xxDragDropCertFiles = files;
            // ###BEGIN###{CertificateManager}
            // ###BEGIN###{PowerControl-Advanced}
            // ###BEGIN###{PowerControl-OneClick}
            if (amtversion > 12) { op2 = '<option value=2>' + "MeshCommander Web Server Root" + '</option>'; }
            // ###END###{PowerControl-OneClick}
            // ###END###{PowerControl-Advanced}
            if (certificateStore.length > 0) { op0 += '<option value=0>' + "Ajouter à partir du gestionnaire de certificats" + '</option>'; }
            if ((!xxDragDropCertFiles) && ((op0 != '') || (op2 != ''))) { x += '<div style=height:26px;margin-top:4px><select onchange=addCertButtonUpdate() id=certoptype style=float:right;width:260px>' + op0 + '<option value=1>' + "Ajouter à partir du fichier de certificat" + '</option>' + op2 + '</select><div style=padding-top:4px>' + "Opération" + '</div></div>'; }
            x += '<div id=dxcertfileop1>';
            var input = '<input id=certopen onchange=addCertButtonUpdate() type=file style=float:right;width:260px accept=".crt,.cer,.pem">';
            if (xxDragDropCertFiles) { input = '<input style=float:right;width:260px readonly disabled value="' + xxDragDropCertFiles[0].name + '">'; }
            x += '<div style=height:26px;margin-top:4px>' + input + '<div style=padding-top:4px>' + "Fichier de certificat" + '</div></div></div>';
            if (certificateStore.length > 0) {
                x += '<div id=dxcertfileop2><div style=height:26px;margin-top:4px><select id=certhandle style=float:right;width:260px>';
                for (var i in certificateStore) {
                    var certificate = certificateStore[i], name = certificate.cert.subject.getField('CN').value;
                    x += '<option value=' + certificate['h'] + '>' + name + '</option>';
                }
                x += '</select><div style=padding-top:4px>' + "Certificat" + '</div></div></div>';
            }
            // ###END###{CertificateManager}
            // ###BEGIN###{!CertificateManager}
            var input = '<input id=certopen onchange=addCertButtonUpdate() type=file style=float:right;width:260px accept=".cer,.pem">';
            if (xxDragDropCertFiles) { input = '<input style=float:right;width:260px readonly disabled value="' + xxDragDropCertFiles[0].name + '">'; }
            x += '<div style=height:26px;margin-top:4px>' + input + '<div style=padding-top:4px>' + "Fichier de certificat" + '</div></div>';
            // ###END###{!CertificateManager}
            x += '<div style=height:26px;margin-top:4px><select id=certtype style=float:right;width:260px><option value=1>' + "Certificat racine de confiance" + '</option><option value=0>' + "Certificat de chaîne" + '</option></select><div style=padding-top:4px>' + "Type de certificat" + '</div></div>';
            setDialogMode(11, "Ajouter un certificat", 3, addCertButtonOk, x);
            addCertButtonUpdate();
        }

        function addCertButtonUpdate() {
            // ###BEGIN###{CertificateManager}
            if ((!xxDragDropCertFiles) && (certificateStore.length > 0)) {
                QV('dxcertfileop2', Q('certoptype').value == 0);
                QV('dxcertfileop1', Q('certoptype').value == 1);
                if (Q('certoptype').value == 0) { QE('idx_dlgOkButton', true); return; }
            }
            // ###END###{CertificateManager}
            var certopen = getInputElement('certopen');
            QE('idx_dlgOkButton', !certopen || (certopen.files.length == 1) || (Q('certoptype').value == 2));
        }

        function addCertButtonOk() {
            // ###BEGIN###{CertificateManager}
            // ###BEGIN###{PowerControl-Advanced}
            // ###BEGIN###{PowerControl-OneClick}
            if (Q('certoptype').value == 2) {
                var certbin = null;
                if (webserver == null) {
                    webserver = CreateWebServer();
                    webserver.generateCertificate(0);
                    certbin = webserver.rootCert;
                    webserver = null;
                } else {
                    certbin = webserver.rootCert;
                }

                // This is a .PEM file, keep everything between BEGIN/END, clean it up and use as-is. It's already Base64.
                var i = certbin.indexOf('-----BEGIN CERTIFICATE-----');
                if (i >= 0) {
                    certbin = certbin.substring(i + 27);
                    i = certbin.indexOf('-----END CERTIFICATE-----');
                    if (i >= 0) certbin = certbin.substring(0, i)
                    certbin = certbin.replace(/\r\n/g, '');
                    if (getSelectElement('certtype').value == 1) {
                        amtstack.AMT_PublicKeyManagementService_AddTrustedRootCertificate(certbin, certificateAdded);
                    } else {
                        amtstack.AMT_PublicKeyManagementService_AddCertificate(certbin, certificateAdded);
                    }
                }
                return;
            }
            // ###END###{PowerControl-OneClick}
            // ###END###{PowerControl-Advanced}
            if ((xxDragDropCertFiles) || (certificateStore.length == 0) || (Q('certoptype').value == 1)) {
                var certopen = getInputElement('certopen');
                var files = xxDragDropCertFiles;
                if (certopen) files = certopen.files;
                if (files && files.length == 1) {
                    var reader = new FileReader();
                    reader.onload = addCertButtonOk2;
                    reader.readAsBinaryString(files[0]);
                }
            } else {
                var certificate = getCertificate(Q('certhandle').value)
                if (getSelectElement('certtype').value == 1) {
                    amtstack.AMT_PublicKeyManagementService_AddTrustedRootCertificate(certificate['certbin'], certificateAdded);
                } else {
                    amtstack.AMT_PublicKeyManagementService_AddCertificate(certificate['certbin'], certificateAdded);
                }
            }
            // ###END###{CertificateManager}
            // ###BEGIN###{!CertificateManager}
            var certopen = getInputElement('certopen');
            var files = xxDragDropCertFiles;
            if (certopen) files = certopen.files;
            if (files && files.length == 1) {
                var reader = new FileReader();
                reader.onload = addCertButtonOk2;
                reader.readAsBinaryString(files[0]);
            }
            // ###END###{!CertificateManager}
        }
        
        function addCertButtonOk2(file) {
            var data = file.target.result;
            var i = data.indexOf('-----BEGIN CERTIFICATE-----');
            if (i >= 0) {
                // This is a .PEM file, keep everything between BEGIN/END, clean it up and use as-is. It's already Base64.
                data = data.substring(i + 27);
                i = data.indexOf('-----END CERTIFICATE-----');
                if (i >= 0) data = data.substring(0, i)
                data = data.replace(/\r\n/g, '');
            } else {
                // This is a .CER file, just base64 encode it and we should be ok.
                data = btoa(data);
            }
            if (getSelectElement('certtype').value == 1) {
                amtstack.AMT_PublicKeyManagementService_AddTrustedRootCertificate(data, certificateAdded);
            } else {
                amtstack.AMT_PublicKeyManagementService_AddCertificate(data, certificateAdded);
            }
        }

        function issueCertButton(files) {
            if (xxdialogMode || !xxAccountAdminName) return;
            xxDragDropCertFiles = files;

            // ###BEGIN###{CertificateManager}
            var x = '', certCount = getCertificateWithKeyCount();
            if ((!xxDragDropCertFiles) && (certCount > 0)) { x += '<div style=height:26px;margin-top:4px><select onchange=addCertButtonUpdate() id=certoptype style=float:right;width:230px><option value=0>' + "Problème du gestionnaire de certificats" + '</option><option value=1>' + "Problème à partir du fichier de certificat" + '</option></select><div style=padding-top:4px>Operation</div></div>'; }
            x += '<div id=dxcertfileop1>', input = '<input id=certopen onchange=issueCertButtonUpdate() type=file style=float:right;width:230px accept=".p12">';
            if (xxDragDropCertFiles) { input = '<input style=float:right;width:230px readonly disabled value="' + xxDragDropCertFiles[0].name + '">'; }
            x += '<div style=height:26px;margin-top:4px>' + input + '<div style=padding-top:4px>' + "Fichier de certificat" + '</div></div><div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certopenpass type=password autocomplete=off style=float:right;width:230px><div style=padding-top:4px>' + "Mot de passe du certificat" + '</div></div></div>';
            if (certificateStore.length > 0) {
                x += '<div id=dxcertfileop2><div style=height:26px;margin-top:4px><select id=certhandle style=float:right;width:230px>';
                for (var i in certificateStore) {
                    var certificate = certificateStore[i], name = certificate.cert.subject.getField('CN').value
                    if (certificate['privateKey']) { x += '<option value=' + certificate['h'] + '>' + name + '</option>'; }
                }
                x += '</select><div style=padding-top:4px>' + "Certificat" + '</div></div></div>';
            }
            // ###END###{CertificateManager}

            // ###BEGIN###{!CertificateManager}
            var x = '', input = '<input id=certopen type=file style=float:right;width:230px onchange=issueCertButtonUpdate() accept=".p12">';
            if (xxDragDropCertFiles) { input = '<input style=float:right;width:230px readonly disabled value="' + xxDragDropCertFiles[0].name + '">'; }
            x += '<div styleheight:26px;margin-top:14px>' + input + '<div style=padding-top:4px>Certificate file</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certopenpass type=password autocomplete=off style=float:right;width:230px><div style=padding-top:4px>' + "Mot de passe du certificat" + '</div></div>';
            // ###END###{!CertificateManager}

            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificat Intel&reg; AMT" + '</i></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certcn style=float:right;width:230px><div style=padding-top:4px>' + "Nom commun" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certo style=float:right;width:230px><div style=padding-top:4px>' + "Organisation" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certst style=float:right;width:230px><div style=padding-top:4px>' + "État / Province" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=issueCertButtonUpdate() id=certc style=float:right;width:230px><div style=padding-top:4px>' + "Pays" + '</div></div>';
            x += '<div>' + "Utilisations du certificat" + '</div><ul style="list-style-type:none;height:100px;overflow:auto;width:100%;border: 1px solid #000;background-color:white;overflow-x:hidden;margin:0;padding:0">';
            //x += '<li><label><input type=checkbox id=d11_cu1>' + "Intel&reg; AMT Console" + '</label></li>';
            //x += '<li><label><input type=checkbox id=d11_cu2>' + "Intel&reg; AMT Agent" + '</label></li>';
            //x += '<li><label><input type=checkbox id=d11_cu3>' + "Intel&reg; AMT Activation" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu4 checked>' + "Serveur TLS (HTTPS)" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu5>' + "Client TLS (HTTPS)" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu6>' + "Protection des e-mails" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu7>' + "Signature du code" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu8>' + "Horodatage" + '</label></li>';
            x += '</ul>';
            setDialogMode(11, "Délivrer un certificat", 3, issueCertButtonOk, x);
            issueCertButtonUpdate();
        }

        function issueCertButtonUpdate() {
            // ###BEGIN###{CertificateManager}
            var certCount = getCertificateWithKeyCount();
            if ((!xxDragDropCertFiles) && (certCount > 0)) {
                QV('dxcertfileop2', Q('certoptype').value == 0);
                QV('dxcertfileop1', Q('certoptype').value == 1);
                QE('idx_dlgOkButton', (getInputElement('certcn').value != '') && (getInputElement('certo').value != '') && (getInputElement('certst').value != '') && (getInputElement('certc').value != ''));
                return;
            }
            // ###END###{CertificateManager}
            var certopen = getInputElement('certopen');
            QE('certopenpass', !certopen || (certopen && certopen.files.length == 1));
            var x = (!certopen || certopen.files.length < 2);
            if ((!certopen || (certopen && certopen.files.length)) == 1 && Q('certopenpass').value == '') x = false;
            if (getInputElement('certcn').value == '' || getInputElement('certo').value == '' || getInputElement('certst').value == '' || getInputElement('certc').value == '') { x = false; }
            QE('idx_dlgOkButton', x);
        }

        function issueCertButtonOk() {
            // ###BEGIN###{CertificateManager}
            if ((xxDragDropCertFiles) || (certificateStore.length == 0) || (Q('certoptype').value == 1)) {
                var certopen = getInputElement('certopen');
                var files = xxDragDropCertFiles;
                if (certopen) files = certopen.files;
                if (files && files.length == 1) {
                    // Issue a certificate using this file
                    var reader = new FileReader();
                    reader.onload = issueCertButtonOk2;
                    reader.readAsBinaryString(files[0]);
                } else {
                    // Issue a certificate using a dummy CA
                    issueCertButtonOk3(null);
                }
            } else {
                // Save the certificate store certificate as a p12 and load it back up using the regular user flow. This makes the code smaller but slower.
                var certificate = getCertificate(Q('certhandle').value);
                var certBase64 = forge.util.encode64(forge.asn1.toDer(forge.pkcs12.toPkcs12Asn1(certificate['privateKey'], certificate['cert'], 'pass')).getBytes());
                amtcert_loadP12File(atob(certBase64), 'pass', issueCertButtonOk3);
            }
            // ###END###{CertificateManager}
            // ###BEGIN###{!CertificateManager}
            var certopen = getInputElement('certopen');
            var files = xxDragDropCertFiles;
            if (certopen) files = certopen.files;
            if (files && files.length == 1) {
                // Issue a certificate using this file
                var reader = new FileReader();
                reader.onload = issueCertButtonOk2;
                reader.readAsBinaryString(files[0]);
            } else {
                // Issue a certificate using a dummy CA
                issueCertButtonOk3(null);
            }
            // ###END###{!CertificateManager}
        }

        function issueCertButtonOk2(file) {
            // Load the CA certificate and private key
            var r = amtcert_loadP12File(file.target.result, Q('certopenpass').value, issueCertButtonOk3);
            if (r == false) { messagebox("Délivrer un certificat", "Impossible de décrypter / décoder le certificat."); return; }
        }

        function issueCertButtonOk3(privateKey, subjectAttributes, cert) {
            // Ask Intel AMT to generate a key pair
            xxCaPrivateKey = privateKey;
            xxCaSubjectAttributes = subjectAttributes;
            amtstack.AMT_PublicKeyManagementService_GenerateKeyPair(0, 2048, GenerateKeyPairResponse);
        }

        function GenerateKeyPairResponse(stack, serviceName, response, status) {
            if (status != 200) { messagebox("Délivrer un certificat", "Impossible de générer la paire de clés. Statut: " + status); return; }
            if (response.Body['ReturnValue'] != 0) { messagebox("Délivrer un certificat", "Impossible de générer la paire de clés," + response.Body['ReturnValueStr']); return; }

            // Get the new key pair
            amtstack.Enum('AMT_PublicPrivateKeyPair', GenerateKeyPairResponse2, response.Body['KeyPair']['ReferenceParameters']['SelectorSet']['Selector']['Value']);
        }

        function GenerateKeyPairResponse2(stack, serviceName, response, status, tag) {
            if (status != 200) { messagebox("Délivrer un certificat", "Impossible de générer la paire de clés. Statut: " + status); return; }
            var DERKey = null;
            for (var i in response) { if (response[i]['InstanceID'] == tag) DERKey = response[i]['DERKey']; }

            // Get certificate values
            var certattributes = { 'CN': getInputElement('certcn').value, 'O': getInputElement('certo').value, 'ST': getInputElement('certst').value, 'C': getInputElement('certc').value };
            var issuerattributes = { 'CN': "Certificat racine non approuvé" };
            if (xxCaPrivateKey != null && xxCaSubjectAttributes) {
                issuerattributes = {};
                for (var i in xxCaSubjectAttributes) {
                    issuerattributes[xxCaSubjectAttributes[i].shortName] = xxCaSubjectAttributes[i].value; // The issuing CA's subject attributes 
                }
            } 

            // Figure out the extended key usages
            var extKeyUsage = { name: 'extKeyUsage' }
            //if (Q('d11_cu1').checked) { extKeyUsage['2.16.840.1.113741.1.2.1'] = true; extKeyUsage.clientAuth = true; }
            //if (Q('d11_cu2').checked) { extKeyUsage['2.16.840.1.113741.1.2.2'] = true; extKeyUsage.clientAuth = true; }
            //if (Q('d11_cu3').checked) { extKeyUsage['2.16.840.1.113741.1.2.3'] = true; extKeyUsage.clientAuth = true; }
            if (Q('d11_cu4').checked) { extKeyUsage.serverAuth = true; }
            if (Q('d11_cu5').checked) { extKeyUsage.clientAuth = true; }
            if (Q('d11_cu6').checked) { extKeyUsage.emailProtection = true; }
            if (Q('d11_cu7').checked) { extKeyUsage.codeSigning = true; }
            if (Q('d11_cu8').checked) { extKeyUsage.timeStamping = true; }

            // Sign the key pair using the CA certifiate
            var cert = amtcert_signWithCaKey(DERKey, xxCaPrivateKey, certattributes, issuerattributes, extKeyUsage);
            if (cert == null) { messagebox("Délivrer un certificat", "Impossible de signer le certificat."); return; }

            // Place the resulting signed certificate back into AMT
            var pem = forge.pki.certificateToPem(cert).replace(/(\r\n|\n|\r)/gm, '');
            amtstack.AMT_PublicKeyManagementService_AddCertificate(pem.substring(27, pem.length - 25), GenerateKeyPairResponse4);
        }

        function GenerateKeyPairResponse4(stack, serviceName, response, status) {
            if (status != 200) { messagebox("Délivrer un certificat", "Impossible de générer la paire de clés. Statut: " + status); return; }
            PullCertificates();
        }

        function certificateAdded(stack, serviceName, response, status) { if (status != 200 || response.Body['ReturnValue'] != 0) { messagebox("Ajouter un certificat", "Impossible d'ajouter le certificat, erreur" + (status != 200 ? status : response.Body['ReturnValueStr'])); } else PullCertificates(); }
        function certificateRemoved(stack, serviceName, header, status) { if (status != 200) { messagebox("Supprimer le certificat", "Impossible de supprimer le certificat, erreur" + status); } else PullCertificates(); }

        function getInputElement(id) { var allelements = document.getElementsByTagName('input'); for (t = 0; t < allelements.length; t++) { if (allelements[t].id == id) return allelements[t]; } }
        function getSelectElement(id) { var allelements = document.getElementsByTagName('select'); for (t = 0; t < allelements.length; t++) { if (allelements[t].id == id) return allelements[t]; } }

        function showSetTlsSecurityDlg(x) {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><select onchange=showSetTlsSecurityDlgUpdate() id=tlscert style=float:right;width:260px><option value=-1>' + "Aucun certificat, TLS désactivé" + '</option>';
            for (var i in xxCertificates) { if (xxCertificates[i].TrustedRootCertficate == false && xxCertificates[i].XPrivateKey) { x += '<option value=' + i + '>' + xxCertificates[i].XSubject['CN'] + '</option>'; } }
            x += '</select><div style=padding-top:4px>' + "Certificat" + '</div></div>';

            x += '<div style=height:26px;margin-top:4px><select id=tlsremote style=float:right;width:260px onchange=showSetTlsSecurityDlgUpdate()><option value=0>Server-auth TLS only</option><option value=1>Server-auth, non-TLS allowed</option>';
            x += '<option value=2>Mutual-auth TLS only</option><option value=3>Mutual-auth, non-TLS allowed</option>'; // Support for mutual-auth TLS seems to have been removed on AMT8 and after ??
            x += '</select><div style=padding-top:4px>Security</div></div><div style=height:26px id=d11rcn title="' + "Liste séparée par des virgules des noms communs de certificats qui seront autorisés à se connecter à distance." + '"><input id=d11_rcn style=float:right;width:260px onkeyup=showSetTlsSecurityDlgUpdate() placeholder="' + "nom1, nom2" + '"><div style=padding-top:4px>' + "CN distants" + '</div></div>';

            setDialogMode(11, "Paramètres TLS", 3, showSetTlsSecurityDlgOk, x);

            // Select the current TLS certificate in the drop down box
            if ((xxTLSCredentialContext.length == 0) || (xxTlsSettings[0]['Enabled'] == false) || (xxTlsSettings[1]['Enabled'] == false)) {
                getSelectElement('tlscert').value = -1;
            } else {
                var certInstanceId = xxTLSCredentialContext[0]['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
                for (var i in xxCertificates) { if (xxCertificates[i]['InstanceID'] == certInstanceId) { getSelectElement('tlscert').value = i; } }
            }

            // Figure out what index is local & remote
            var localNdx = ((xxTlsSettings[0]['InstanceID'] == 'Intel(r) AMT LMS TLS Settings')) ? 0 : 1, remoteNdx = (1 - localNdx);

            // Select correct TLS options in the drop down boxes
            getSelectElement('tlsremote').value = ((xxTlsSettings[remoteNdx]['MutualAuthentication'] == true) ? 2 : 0) + ((xxTlsSettings[remoteNdx]['AcceptNonSecureConnections'] == true) ? 1 : 0);
            if (xxTlsSettings[remoteNdx]['TrustedCN']) { Q('d11_rcn').value = MakeToArray(xxTlsSettings[remoteNdx]['TrustedCN']).join(', '); }

            showSetTlsSecurityDlgUpdate();
        }

        function showSetTlsSecurityDlgUpdate() {
            var h = getSelectElement('tlscert').value;
            QE('tlsremote', h != -1);
            QV('d11rcn', (h != -1) && (getSelectElement('tlsremote').value > 1));
            var ok = true;
            if ((getSelectElement('tlsremote').value > 1) && (!splitDomains(Q('d11_rcn').value))) { ok = false; }
            QE('idx_dlgOkButton', ok);
        }

        var setTlsSecurityPendingCalls;
        var setTlsSecurityDeleteCredentialContext;
        function showSetTlsSecurityDlgOk() {
            var h = getSelectElement('tlscert').value;
            var r = getSelectElement('tlsremote').value;
            var xxTlsSettings2 = Clone(xxTlsSettings);
            setTlsSecurityPendingCalls = 0;
            setTlsSecurityDeleteCredentialContext = null;

            if (h != -1) {
                // Set the TLS certificate
                if (xxTLSCredentialContext.length > 0) {
                    // Modify the current context
                    var newTLSCredentialContext = Clone(xxTLSCredentialContext[0]);
                    newTLSCredentialContext['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'] = xxCertificates[h]['InstanceID'];
                    amtstack.Put('AMT_TLSCredentialContext', newTLSCredentialContext, setTlsSecurityResponse, 0, 1);
                    setTlsSecurityPendingCalls++;
                } else {
                    // Add a new security context
                    amtstack.Create('AMT_TLSCredentialContext', {
                        'ElementInContext':'<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + xxCertificates[h]['InstanceID'] + '</w:Selector></w:SelectorSet></a:ReferenceParameters>',
                        'ElementProvidingContext':'<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_TLSProtocolEndpointCollection') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="ElementName">TLSProtocolEndpointInstances Collection</w:Selector></w:SelectorSet></a:ReferenceParameters>' }, setTlsSecurityResponse);
                    setTlsSecurityPendingCalls++;
                }
            } else {
                // Clear the TLS certificate association (MOVE THIS)
                if (xxTLSCredentialContext.length > 0) { setTlsSecurityDeleteCredentialContext = Clone(xxTLSCredentialContext[0]); }
            }

            // Figure out what index is local & remote
            var localNdx = ((xxTlsSettings[0]['InstanceID'] == 'Intel(r) AMT LMS TLS Settings')) ? 0 : 1, remoteNdx = (1 - localNdx);

            // Remote TLS settings
            xxTlsSettings2[remoteNdx]['Enabled'] = (h != -1);
            xxTlsSettings2[remoteNdx]['MutualAuthentication'] = (r >= 2);
            xxTlsSettings2[remoteNdx]['AcceptNonSecureConnections'] = ((r % 2) == 1);
            xxTlsSettings2[remoteNdx]['TrustedCN'] = splitDomains(Q('d11_rcn').value);
            
            // Local TLS settings
            xxTlsSettings2[localNdx]['Enabled'] = (h != -1);
            xxTlsSettings2[localNdx]['TrustedCN'] = splitDomains(Q('d11_rcn').value); // This is required for old Intel AMT (v7 for sure) because older AMT support local interface mutual-auth and don't well if you don't set this.

            // Mutual-auth TLS requires time sync
            if (r >= 2) {
                setTlsSecurityPendingCalls++;
                amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(function (stack, name, response, status) {
                    if (status != 200) { messagebox('', "Impossible de régler l'heure, état =" + status); return; }
                    if (response.Body['ReturnValue'] != 0) { messagebox('', "Impossible de régler l'heure, erreur: " + response.Body['ReturnValueStr']); return; }
                    //var now = new Date(), Tm1 = Math.round((now.getTime() - (now.getTimezoneOffset() * 60000)) / 1000);
                    var now = new Date(), Tm1 = Math.round(now.getTime() / 1000);
                    amtstack.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch(response.Body['Ta0'], Tm1, Tm1, function () { setTlsSecurityResponse(); });
                });
            }

            // Update TLS settings
            setTlsSecurityPendingCalls += 2;
            amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[0], setTlsSecurityResponse, 0, 1, xxTlsSettings2[0]);
            amtstack.Put('AMT_TLSSettingData', xxTlsSettings2[1], setTlsSecurityResponse, 0, 1, xxTlsSettings2[1]);

            statusbox("Paramètres TLS", "Application de nouveaux paramètres de sécurité ...");
        }

        // Split a string into a array of domains. Return null if not a valid list.
        function splitDomains(str) {
            str = str.split(',');
            if (str.length == 0) return;
            for (var i in str) { str[i] = str[i].trim(); if ((str[i].indexOf(' ') >= 0) || (str[i].length == 0)) return; }
            if (str.length > 4) return;
            return str;
        }

        function setTlsSecurityResponse(stack, name, response, status) {
            if (stack) {
                if (status != 200) { messagebox('', "Impossible de définir la sécurité TLS, état =" + status); return; }
                if (response.Body['ReturnValueStr'] && !methodcheck(response)) return;
            }

            // Check if all the calls are done & perform a commit
            if ((--setTlsSecurityPendingCalls) == 0) { amtstack.AMT_SetupAndConfigurationService_CommitChanges(null, setTlsSecurityResponse2); }
        }

        function setTlsSecurityResponse2(stack, name, response, status) {
            if (status != 200) { messagebox('', "Impossible de définir la sécurité TLS, état =" + status); return; }
            if (response.Body['ReturnValue'] != 0) { messagebox('', "Impossible de définir la sécurité TLS, erreur: " + response.Body['ReturnValueStr']); return; }
            setTimeout(setTlsSecurityResponse3, 2000);
        }

        function setTlsSecurityResponse3() {
            if (setTlsSecurityDeleteCredentialContext != null) { amtstack.Delete('AMT_TLSCredentialContext', setTlsSecurityDeleteCredentialContext, function () { }); }
            PullCertificates();
            setDialogMode();
            amtstack.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch(processSystemTime);
        }

// ###END###{Certificates}

// ###BEGIN###{AgentPresence}

        //
        // AGENT PRESENCE
        //

        var xxWatchdog = null;

        function PullWatchdog() {
            amtstack.BatchEnum(null, ['*AMT_AgentPresenceCapabilities', 'AMT_AgentPresenceWatchdog', 'AMT_AgentPresenceWatchdogAction', 'AMT_StateTransitionCondition', 'CIM_ConcreteDependency'], PullWatchdogResponse);
        }

        function PullWatchdogResponse(stack, name, responses, status) {
            if ((status == 200) && (responses['AMT_AgentPresenceCapabilities'].status == 200)) {
                xxWatchdog = responses;
            
                // Place the actions into the watchdogs for easy navigation.
                for (var i in xxWatchdog['CIM_ConcreteDependency'].responses) {
                    var link = xxWatchdog['CIM_ConcreteDependency'].responses[i];
                    var x1 = getItem(link['Antecedent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'CreationClassName');
                    if (x1 && x1['Value'] == 'AMT_AgentPresenceWatchdog') {
                        var deviceid = getItem(link['Antecedent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'DeviceID')['Value'];
                        var policyConditionName = getItem(link['Dependent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'PolicyConditionName')['Value'];
                        var watchdog = getItem(xxWatchdog['AMT_AgentPresenceWatchdog'].responses, 'DeviceID', deviceid);
                        var transitionPolicy = getItem(xxWatchdog['AMT_StateTransitionCondition'].responses, 'PolicyConditionName', policyConditionName);
                        if (!watchdog.transitions) watchdog.transitions = [];
                        watchdog.transitions.push(transitionPolicy);
                    }
                    if (x1 && x1['Value'] == 'AMT_StateTransitionCondition') {
                        var policyConditionName = getItem(link['Antecedent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'PolicyConditionName')['Value'];
                        var policyActionName = getItem(link['Dependent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'PolicyActionName')['Value'];
                        var transitionPolicy = getItem(xxWatchdog['AMT_StateTransitionCondition'].responses, 'PolicyConditionName', policyConditionName);
                        var watchdogAction = getItem(xxWatchdog['AMT_AgentPresenceWatchdogAction'].responses, 'PolicyActionName', policyActionName);
                        if (!transitionPolicy.actions) transitionPolicy.actions = [];
                        transitionPolicy.actions.push(watchdogAction);
                    }
                }

                updateWatchdog();
                QV('go19', true); // Show Agent Presence panel
            }
        }

        var watchdogEnabledStates = [ "Inconnue", "Autre", "Activée", "désactivé", "Éteindre", "N'est pas applicable", "Activé mais hors ligne", "En test", "Différé", "Au repos", "Départ" ];
        var watchdogMonitoredEntity = [ "Inconnue", "Autre", "Système opérateur", "Processus de démarrage du système d'exploitation", "Processus d'arrêt du système d'exploitation", "Processus de démarrage du micrologiciel", "Processus de démarrage du BIOS", "Application", "Processeur de service" ];
        function updateWatchdog() {
            if (xxWatchdog == null) return;
            var x = '';

            // Global Agent Presense Values
            x += TableStart();
            x += TableEntry("Nombre maximum", xxWatchdog['AMT_AgentPresenceCapabilities'].response['MaxTotalAgents'] + " chiens de garde");
            x += TableEntry("Nombre total maximum d'actions", xxWatchdog['AMT_AgentPresenceCapabilities'].response['MaxTotalActions'] + " Actions");
            // x += TableEntry("Maximum EAC Watchdogs", xxWatchdog['AMT_AgentPresenceCapabilities'].response['MaxEacAgents'] + " watchdogs");
            x += TableEnd() + '<br>';

            // Watchdogs
            x += TableStart2();
            x += '<tr><td class=r1 style=padding-left:15px><br>' + "Gérez les chiens de garde de présence d'agent Intel&reg; AMT." + '<br><br>';
            if ((xxWatchdog['AMT_AgentPresenceWatchdog'].responses == null) || (xxWatchdog['AMT_AgentPresenceWatchdog'].responses.length == 0)) {
                x += '<div style=padding-left:15px><i>' + "Aucun chien de garde de présence d'agent n'a été trouvé." + '</i></div><br>';
            } else {
                for (var i in xxWatchdog['AMT_AgentPresenceWatchdog'].responses) {
                    var w = xxWatchdog['AMT_AgentPresenceWatchdog'].responses[i];
                    var n = guidToStr(rstr2hex(atob(w['DeviceID'])));
                    if (w['MonitoredEntityDescription'] && w['MonitoredEntityDescription'] != '') n = EscapeHtml(w['MonitoredEntityDescription']);
                    x += '<div class=itemBar onclick=showWatchdogDetails(' + i + ')><input type=button style=float:right value="' + "Ajouter une action ..." + '" onclick=addWatchdogAction(event,' + i + ')>';
                    if (w.transitions) { x += '<input type=button style=float:right value="' + "Supprimer des actions ..." + '" onclick=deleteWatchdogActions(event,' + i + ')>'; }
                    x += '<div style=padding-top:3px><b>' + n + '</b>, ' + amtstack.WatchdogCurrentStates[w['CurrentState']] + '</div>';
                    var xx = '';
                    for (var j in w.transitions) {
                        var t = w.transitions[j];
                        if (xx != '') xx += '<br>';
                        xx += getWatchdogTransitionStr(t['OldState']) + ' &rarr; ' + getWatchdogTransitionStr(t['NewState']);
                        if (t.actions) {
                            var action = t.actions[0];
                            if (action['EventOnTransition'] == true) { xx += " : Événement à consigner"; }
                        }
                    }
                    if (xx != '') { x += '<div style=padding:12px>' + xx + '</div>'; }
                    x += '</div>';
                }
            }
            x += '<br>';
            x += TableEnd(AddRefreshButton('PullWatchdog()') + AddButton("Ajouter un chien de garde ...", 'AddWatchdog()'));
            x += '<br>';

            QH('id_TableSystemAgentPresence', x);
        }

        function getWatchdogTransitionStr(s) {
            if (s == 31) return "N'importe quel État";
            var x = '';
            for (var i in amtstack.WatchdogCurrentStates) { if ((s & i) != 0) { x += ', ' + amtstack.WatchdogCurrentStates[i]; } }
            return x.substring(2);
        }

        function showWatchdogDetails(i) {
            var w = xxWatchdog['AMT_AgentPresenceWatchdog'].responses[i];

            var x = '';
            //x += addHtmlValue("DeviceID", guidToStr(rstr2hex(atob(w['DeviceID']))));
            if (w['MonitoredEntityDescription'] && w['MonitoredEntityDescription'] != '') x += addHtmlValue("La description", EscapeHtml(w['MonitoredEntityDescription']));
            x += addHtmlValue("Entité surveillée", watchdogMonitoredEntity[w['MonitoredEntity']]);
            x += addHtmlValue("État actuel", amtstack.WatchdogCurrentStates[w['CurrentState']]);
            x += addHtmlValue("État activé", watchdogEnabledStates[w['EnabledState']]);
            x += addHtmlValue("Intervalle de démarrage", w['StartupInterval'] + " seconde (s)");
            x += addHtmlValue("Intervalle de temporisation", w['TimeoutInterval'] + " seconde (s)");

            setDialogMode(11, format("Chien de garde {0}", guidToStr(rstr2hex(atob(w['DeviceID'])))), 5, showWatchdogDetailsOk, x, w);
        }

        function showWatchdogDetailsOk(x, w) {
            if (x == 2) {
                amtstack.Delete('AMT_AgentPresenceWatchdog', { 'DeviceID': w['DeviceID'] }, PullWatchdog);
            }
        }

        function AddWatchdog() {
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input id=wgname style=float:right;width:240px maxlength=16 onkeyup=AddWatchdogUpdate()><div style=padding-top:4px>' + "Nom" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=wgguid style=float:right;width:240px maxlength=36 onkeyup=AddWatchdogUpdate()><div style=padding-top:4px title="' + "Générer un DeviceID aléatoire" + '">' + addLink("Reference de l'appareil", 'GenerateWatchdogGuid()') + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=wgstart style=float:right;width:240px maxlength=8 placeholder=3600 onkeyup=AddWatchdogUpdate()><div style=padding-top:4px>' + "Démarrage (secondes)" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input id=wgtimeout style=float:right;width:240px maxlength=8 placeholder=60 onkeyup=AddWatchdogUpdate()><div style=padding-top:4px>' + "Délai d'expiration (secondes)" + '</div></div>';
            setDialogMode(11, "Ajouter un chien de garde", 3, AddWatchdogOk, x);
            AddWatchdogUpdate();
        }

        function GenerateWatchdogGuid() {
            var i, guid = '';
            for (i = 0; i < 16; i++) { guid += String.fromCharCode(random(255)); }
            Q('wgguid').value = guidToStr(rstr2hex(guid));
            AddWatchdogUpdate();
        }

        function AddWatchdogUpdate() {
            var ok = (Q('wgstart').value == '' || parseInt(Q('wgstart').value) > 0) && (Q('wgtimeout').value == '' || parseInt(Q('wgtimeout').value) > 0);
            var gc = 0, g = Q('wgguid').value.toLowerCase();
            for (var i = 0; i < g.length; i++) {
                var c = g.charCodeAt(i);
                if (c == 45) continue;
                if ((c >= 48 && c <= 57) || (c >= 97 && c <= 102)) { gc++; } else { ok = false; }
            }
            if (gc != 32) ok = false;
            QE('dlgOkButton', ok);
        }

        function AddWatchdogOk() {
            var timeout = Q('wgtimeout').value, startup = Q('wgstart').value;
            if (timeout == '') timeout = 60;
            if (startup == '') startup = 3600;
            var guid = btoa(hex2rstr(guidToStr(Q('wgguid').value.replace(/-/g, '')).replace(/-/g, '')));
            var wdog = { 'CreationClassName': 0, 'DeviceID': guid, 'StartupInterval': startup, 'SystemCreationClassName': 0, 'SystemName': 0, 'TimeoutInterval': timeout, 'MonitoredEntityDescription': Q('wgname').value };
            amtstack.Create('AMT_AgentPresenceWatchdog', wdog, AddWatchdogOk2);
        }

        function AddWatchdogOk2(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Chien de garde", "Impossible d'ajouter le chien de garde, erreur #" + status);
            } else {
                PullWatchdog();
            }
        }

        function addWatchdogAction(e, i) {
            var w = xxWatchdog['AMT_AgentPresenceWatchdog'].responses[i];
            var x = '<table>';
            x += '<td style=width:180px>' + "De" + '<br>'
            for (var i in amtstack.WatchdogCurrentStates) {
                x += '<input id=wgsa' + i + ' type=checkbox onclick=addWatchdogActionUpdate()> ' + amtstack.WatchdogCurrentStates[i] + '<br />';
            }
            x += '<td>' + "À" + '<br>'
            for (var i in amtstack.WatchdogCurrentStates) {
                x += '<input id=wgsb' + i + ' type=checkbox onclick=addWatchdogActionUpdate()> ' + amtstack.WatchdogCurrentStates[i] + '<br />';
            }
            x += '</table><br>' + "Faire une action" + '<br><input id=wgsevent type=checkbox checked onclick=addWatchdogActionUpdate()>' + "Écrire dans le journal des événements" + '<br />';
            setDialogMode(11, "Ajouter une action de surveillance", 3, addWatchdogActionOk, x, w);
            addWatchdogActionUpdate();
            haltEvent(e);
        }

        function addWatchdogActionUpdate() {
            var tfrom = 0, tto = 0;
            for (var i in amtstack.WatchdogCurrentStates) {
                if (Q('wgsa' + i).checked == true) tfrom += parseInt(i);
                if (Q('wgsb' + i).checked == true) tto += parseInt(i);
            }
            QE('dlgOkButton', tfrom > 0 && tto > 0 && Q('wgsevent').checked == true);
        }

        function addWatchdogActionOk(b, w) {
            var tfrom = 0, tto = 0;
            for (var i in amtstack.WatchdogCurrentStates) {
                if (Q('wgsa' + i).checked == true) tfrom += parseInt(i);
                if (Q('wgsb' + i).checked == true) tto += parseInt(i);
            }
            amtstack.AMT_AgentPresenceWatchdog_AddAction(tfrom, tto, Q('wgsevent').checked, null, null, AddWatchdogActionResponse, null, 0, { 'DeviceID': w['DeviceID'] });
        }

        function AddWatchdogActionResponse(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Watchdog Action", "Impossible d'ajouter une action de surveillance, erreur #" + status);
            } else {
                PullWatchdog();
            }
        }

        function deleteWatchdogActions(e, i) {
            var w = xxWatchdog['AMT_AgentPresenceWatchdog'].responses[i];
            setDialogMode(11, "Supprimer les actions du chien de garde", 3, deleteWatchdogActionsOk, "Supprimer toutes les actions de ce chien de garde?", w);
            haltEvent(e);
        }

        function deleteWatchdogActionsOk(b, w) {
            amtstack.AMT_AgentPresenceWatchdog_DeleteAllActions(deleteWatchdogActionResponse, null, 0, { 'DeviceID': w['DeviceID'] });
        }

        function deleteWatchdogActionResponse(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Watchdog Action", "Impossible de supprimer les actions du chien de garde, erreur #" + status);
            } else {
                PullWatchdog();
            }
        }

// ###END###{AgentPresence}
        
// ###BEGIN###{SystemDefense}

        //
        // SYSTEM DEFENSE PANEL
        //

        var xxSystemDefense = null;
        var xxSystemDefenceLinkedPolicy = {};
        var xxUpdatingDefenseStats = false;
        var xxFilterStatistics = [{}, {}]; // Wired and wireless interface stats
        var xxFilterStatisticsTimer = null;
        var xxFilterStatisticsTimerActive = false;

        var xxSystemDefenceFilterEthernetTypes = { 2048: "Tous les paquets IP", 2054: "Tous les paquets ARP" };
        var xxSystemDefenceFilterIPTypes = { 4: "IPv4", 6: "IPv6" };
        var xxSystemDefenceFilterDesc = { 0: "Autoriser, compter", 1: "Drop, Count", 2: "Limite de taux", 3: "Autoriser", 4: "Laissez tomber" };
        var xxSystemDefenceFilters = { 'HdrProtocolID': 1, 'HdrDestAddress': 2, 'HdrDestMask': 2, 'HdrSrcAddress': 2, 'HdrSrcMask': 2, 'HdrSrcPortStart': 1, 'HdrSrcPortEnd': 1, 'HdrDestPortStart': 1, 'HdrDestPortEnd': 1, 'HdrSrcAddressEndOfRange': 2, 'HdrDestAddressEndOfRange ': 2, 'TCPFlagsOn': 3, 'TCPFlagsOff': 3 };

        function PullSystemDefense() {
            amtFirstPull |= 4;
            amtstack.BatchEnum(null, ['AMT_SystemDefensePolicy', 'AMT_NetworkPortSystemDefensePolicy', 'AMT_Hdr8021Filter', 'AMT_IPHeadersFilter', 'AMT_NetworkFilter'], PullSystemDefenseResponse);
        }

        function PullSystemDefenseResponse(stack, name, responses, status) {
            if (status == 200) {
                xxSystemDefense = responses;
                updateSystemDefense();
                QV('go18', true); // Show System Defense Panel
                if (urlvars['norefresh']) { UpdateDefenseStats(); } // If norefresh is set, pull the system defense stats now.
            }
        }

        function updateSystemDefense() {
            if (xxSystemDefense == null) return;
            var x = '';

            // Get active policies
            xxSystemDefenceLinkedPolicy = {};
            for (var i in xxSystemDefense['AMT_NetworkPortSystemDefensePolicy'].responses) {
                var link = xxSystemDefense['AMT_NetworkPortSystemDefensePolicy'].responses[i];
                var a = +getItem(link['Antecedent']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'DeviceID')['Value'].substring(27);
                var b = link['Dependent']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
                var p = getItem(xxSystemDefense['AMT_SystemDefensePolicy'].responses, 'InstanceID', b);
                xxSystemDefenceLinkedPolicy[a] = p;
            }

            // Global System Defense settings
            x += TableStart();
            var policyname = ('<i>' + "Aucun" + '</i>');
            if (xxSystemDefenceLinkedPolicy[0]) { policyname = xxSystemDefenceLinkedPolicy[0]['PolicyName']; }
            x += TableEntry("Stratégie câblée par défaut", addLink(policyname, 'changeDefaultPolicy(0)'));
            /*
            policyname = ('<i>' + "None" + '</i>');
            if (xxSystemDefenceLinkedPolicy[1]) { policyname = xxSystemDefenceLinkedPolicy[1]['PolicyName']; }
            x += TableEntry("Default Wireless Policy", addLink(policyname, 'changeDefaultPolicy(1)'));
            */

            // Filter Statistics
            for (var i = 0; i < 2; i++) {
                var f = xxFilterStatistics[i];
                for (var j in f) {
                    var c = f[j];
                    if (c == 1) c += " paquet"; else c += " paquets";
                    var jn = ((i==0)?"Filaire":"Sans fil") + j;
                    x += TableEntry(jn, c);
                }
            }
            x += TableEnd();
            x += '<br>';

            x += TableStart2();
            x += '<tr><td class=r1 style=padding-left:15px;border:0><br>' + "Gérez les politiques de défense du système Intel&reg; AMT." + '<br><br>';
            if (xxSystemDefense['AMT_SystemDefensePolicy'].responses.length == 0) {
                x += '<div style=padding-left:15px><i>' + "Aucune politique de défense du système trouvée." + '</i></div><br>';
            } else {
                for (var i in xxSystemDefense['AMT_SystemDefensePolicy'].responses) {
                    var policy = xxSystemDefense['AMT_SystemDefensePolicy'].responses[i];
                    var desc = '';
                    if (policy['FilterCreationHandles']) {
                        policy['FilterCreationHandles'] = MakeToArray(policy['FilterCreationHandles']);
                        var c = policy['FilterCreationHandles'].length;
                        desc = ', ' + c + ' filter' + (c > 1?'s':'');
                    }
                    x += '<div class=itemBar onclick=showPolicyDetails(' + i + ')><div style=padding-top:3px><b>' + EscapeHtml(policy['PolicyName']) + '</b>' + desc + '</div></div>';
                }
            }

            x += '<tr><td class=r1 style=padding-left:15px><br>' + "Gérez les filtres de défense du système Intel&reg; AMT." + '<br><br>';
            if (xxSystemDefense['AMT_Hdr8021Filter'].responses.length == 0 && xxSystemDefense['AMT_IPHeadersFilter'].responses.length == 0) {
                x += '<div style=padding-left:15px><i>' + "Aucun filtre de défense du système n'a été trouvé." + '</i></div><br>';
            } else {
                for (var i in xxSystemDefense['AMT_Hdr8021Filter'].responses) {
                    var filter = xxSystemDefense['AMT_Hdr8021Filter'].responses[i];
                    var desc = xxSystemDefenceFilterEthernetTypes[filter['HdrProtocolID8021']];
                    if (!desc) desc = "Protocole Ethernet" + filter['HdrProtocolID8021'];
                    desc += ', ' + xxSystemDefenceFilterDesc[filter['FilterProfile']];
                    if (filter['FilterProfile'] == 2) { desc += " à" + filter['FilterProfileData'] + " paquet / s"; }
                    if (filter['ActionEventOnMatch'] == true) desc += ", Événement sur match";
                    x += '<div class=itemBar onclick=showFilterDetails(0,' + i + ')><div style=padding-top:3px><b>' + (filter['FilterDirection'] == 0 ? '&#8592; ' : '&#8594; ') + EscapeHtml(filter['Name']) + '</b>, ' + desc + '</div></div>';
                }
                for (var i in xxSystemDefense['AMT_IPHeadersFilter'].responses) {
                    var filter = xxSystemDefense['AMT_IPHeadersFilter'].responses[i];
                    var desc = xxSystemDefenceFilterIPTypes[filter['HdrIPVersion']];
                    if (!desc) desc = "Protocole Ethernet" + filter['HdrIPVersion'];
                    desc += ', ' + xxSystemDefenceFilterDesc[filter['FilterProfile']];
                    if (filter['FilterProfile'] == 2) { desc += " à" + filter['FilterProfileData'] + " paquet / s"; }
                    if (filter['ActionEventOnMatch'] == true) desc += ", Événement sur match";
                    var filtercount = 0;
                    for (var j in xxSystemDefenceFilters) { if (filter[j]) filtercount++; }
                    if (filtercount > 0) desc += ', ' + filtercount + ' filter' + (filtercount>1?'s':'');
                    x += '<div class=itemBar onclick=showFilterDetails(1,' + i + ')><div style=padding-top:3px><b>' + (filter['FilterDirection'] == 0 ? '&#8592; ' : '&#8594; ') + EscapeHtml(filter['Name']) + '</b>, ' + desc + '</div></div>';
                }
            }
            x += '<br><td class=r1>' + TableEnd(AddRefreshButton('PullSystemDefense()') + /*AddButton("Update Stats", 'UpdateDefenseStats()') +*/ AddButton("Ajouter un filtre ...", 'AddDefenseFilter()') + AddButton("Ajouter une stratégie ...", 'AddDefensePolicy()'));

            QH('id_TableSystemDefense', x);

            if (xxFilterStatisticsTimer == null) {
                xxFilterStatisticsTimerActive = false;
                if (!urlvars['norefresh']) {
                    UpdateDefenseStats();
                    xxFilterStatisticsTimer = setInterval(UpdateDefenseStats, 5000);
                }
            }
        }

        function StopDefenseStatsTimer() {
            if (xxFilterStatisticsTimer != null) { clearInterval(xxFilterStatisticsTimer); xxFilterStatisticsTimer = null; }
            xxFilterStatisticsTimerActive = false;
        }

        function UpdateDefenseStats(n) {
            if (!n && xxFilterStatisticsTimerActive == true) { return; }
            xxFilterStatisticsTimerActive = true;
            var network = n?n:0;
            if (xxSystemDefenceLinkedPolicy[network]) {
                var eref = '<a:Address></a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_EthernetPort</w:ResourceURI><w:SelectorSet><w:Selector Name="DeviceID">Intel(r) AMT Ethernet Port ' + network + '</w:Selector></w:SelectorSet></a:ReferenceParameters>';
                amtstack.AMT_SystemDefensePolicy_UpdateStatistics(eref, false, UpdateDefenseStats2, network, 0, { 'InstanceID': xxSystemDefenceLinkedPolicy[network]['InstanceID'] });
            } else {
                // No active policy, stop the timer
                xxFilterStatistics[network] = {};
                StopDefenseStatsTimer();
            }
        }

        function UpdateDefenseStats2(stack, name, responses, status, network) {
            if (status == 200) {
                amtstack.Enum('AMT_ActiveFilterStatistics', UpdateDefenseStats3, network);
            } else {
                StopDefenseStatsTimer();
            }
        }

        function UpdateDefenseStats3(stack, name, responses, status, network) {
            var count = 0;
            if (status == 200) {
                xxFilterStatistics[network] = {};
                for (var i in responses) {
                    var readcount = responses[i]['ReadCount'];
                    // var matched = responses[i]['FilterMatched'];
                    var name = getItem(responses[i]['Dependent']['ReferenceParameters']['SelectorSet']['Selector'][1]['Value']['EndpointReference']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'Name')['Value'];
                    xxFilterStatistics[network][name] = readcount;
                    count++;
                }
                updateSystemDefense();
            }
            xxFilterStatisticsTimerActive = false;
            // If there is no statistics, stop the timer
            if (count == 0) { StopDefenseStatsTimer(); } // TODO: Change this to allow for wireless
        }

        function changeDefaultPolicy(network) {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><select id=policySelection style=float:right;width:266px><option value=-1>' + "Aucun";
            for (var i in xxSystemDefense['AMT_SystemDefensePolicy'].responses) { x += '<option value=' + i + ((xxSystemDefenceLinkedPolicy[network] && xxSystemDefense['AMT_SystemDefensePolicy'].responses[i]['InstanceID'] == xxSystemDefenceLinkedPolicy[network]['InstanceID']) ? ' selected' : '') + '>' + xxSystemDefense['AMT_SystemDefensePolicy'].responses[i]['PolicyName']; }
            x += '</select><div style=padding-top:4px>' + "Politique par défaut" + '</div></div>';
            setDialogMode(11, "Politique de défense du système par défaut", 3, changeDefaultPolicyOk, x, network);
        }

        function changeDefaultPolicyOk(button, network) {
            var i = Q('policySelection').value;
            var oldpolicy = xxSystemDefenceLinkedPolicy[network];
            if (oldpolicy) { amtstack.Delete('AMT_NetworkPortSystemDefensePolicy', '<w:SelectorSet><w:Selector Name="Antecedent"><a:EndpointReference xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_EthernetPort</w:ResourceURI><w:SelectorSet><w:Selector Name="CreationClassName">CIM_EthernetPort</w:Selector><w:Selector Name="DeviceID">Intel(r) AMT Ethernet Port ' + network + '</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference></w:Selector><w:Selector Name="Dependent"><a:EndpointReference xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SystemDefensePolicy</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + oldpolicy['InstanceID'] + '</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference></w:Selector></w:SelectorSet>', ((i == -1) ? PullSystemDefense : function () { })); }

            if (i >= 0) {
                var policy = xxSystemDefense['AMT_SystemDefensePolicy'].responses[i];
                var eref = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_EthernetPort</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="DeviceID">' + "Port Ethernet Intel (r) AMT" + ' ' + network + '</Selector></SelectorSet></ReferenceParameters>';
                var pref = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SystemDefensePolicy</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + policy['InstanceID'] + '</Selector></SelectorSet></ReferenceParameters>';
                amtstack.Create('AMT_NetworkPortSystemDefensePolicy', { 'Antecedent': eref, 'Dependent': pref }, changeDefaultPolicyOk2);
            }
        }

        function changeDefaultPolicyOk2(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Politique de défense du système par défaut", "Impossible de définir la stratégie, erreur" + status);
            } else {
                PullSystemDefense();
            }
        }

        function AddDefenseFilter() {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input id=filtername style=float:right;width:260px maxlength=16 onkeyup=AddDefenseFilterUpdate()><div style=padding-top:4px>' + "Nom" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=filtertype style=float:right;width:266px onchange=AddDefenseFilterUpdate()><option value=0>' + "Filtre de paquets IP Ethernet" + '<option value=1>' + "Filtre de paquets Ethernet ARP" + '<option value=2>' + "Filtre de paquets IPv4" + '<option value=3>' + "Filtre de paquets IPv6" + '</select><div style=padding-top:4px>' + "Type" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=ipfilterdiv><input id=ipfilter style=float:right;width:260px placeholder=\"' + "Règles facultatives" + '\" onkeyup=AddDefenseFilterUpdate()><div style=padding-top:4px>' + "Règles de correspondance" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=filterdir style=float:right;width:266px onchange=AddDefenseFilterUpdate()><option value=0>' + "Sortant / Transmettre" + '<option value=1>' + "Entrant / Recevoir" + '</select><div style=padding-top:4px>' + "Direction" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=filterprofile style=float:right;width:266px onchange=AddDefenseFilterUpdate()><option value=0>' + "Autoriser, compter" + '<option value=1>' + "Drop, Count" + '<option value=2>' + "Limite de taux" + '<option value=3>' + "Autoriser" + '<option value=4>' + "Laissez tomber" + '</select><div style=padding-top:4px>' + "action" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px id=filterdatadiv><input id=filterdata style=float:right;width:260px maxlength=8 onkeyup=AddDefenseFilterUpdate()><div style=padding-top:4px>' + "Paquets / seconde" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=filteraction style=float:right;width:266px onchange=AddDefenseFilterUpdate()><option value=false>' + "Ne fais rien" + '<option value=1>' + "Événement sur match" + '</select><div style=padding-top:4px>' + "Journal des événements" + '</div></div>';
            setDialogMode(11, "Ajouter un filtre de défense du système", 3, AddDefenseFilterOk, x);
            AddDefenseFilterUpdate();
        }

        function AddDefenseFilterOk() {
            if (Q('filtertype').value <= 1) {
                // Add Ethernet IP or ARP filter
                var protocol = (Q('filtertype').value == 0) ? 2048 : 2054; // IP : ARP
                var filter = { 'InstanceID ': 0, 'Name': Q('filtername').value, 'CreationClassName': 0, 'SystemName': 0, 'SystemCreationClassName': 0, 'HdrProtocolID8021': protocol, 'FilterProfile': Q('filterprofile').value, 'FilterDirection': Q('filterdir').value, 'ActionEventOnMatch': Q('filteraction').value };
                if (Q('filterprofile').value == 2) filter['FilterProfileData'] = Q('filterdata').value;
                amtstack.Create('AMT_Hdr8021Filter', filter, AddDefenseFilterOk2);
            } else {
                // Add IPv4 or IPv6 Filter
                var protocol = (Q('filtertype').value == 2) ? 4 : 6; // IPv4 : IPv6
                var filter = { 'InstanceID ': 0, 'Name': Q('filtername').value, 'CreationClassName': 0, 'SystemName': 0, 'SystemCreationClassName': 0, 'HdrIPVersion': protocol, 'FilterProfile': Q('filterprofile').value, 'FilterDirection': Q('filterdir').value, 'ActionEventOnMatch': Q('filteraction').value };

                // Parse the filter string
                // https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/default.htm?turl=HTMLDocuments%2FWS-Management_Class_Reference%2FAMT_Hdr8021Filter.htm
                var filterstrs = Q('ipfilter').value.split(',');
                for (var i in filterstrs) {
                    var xx = filterstrs[i].indexOf('=');
                    var n = filterstrs[i].substring(0, xx);
                    var v = filterstrs[i].substring(xx + 1);
                    var t = xxSystemDefenceFilters[n];
                    if (!t) { n = "Hdr" + n; t = xxSystemDefenceFilters[n]; }
                    if (t) {
                        // TODO: Parse v (the value) based on the type t.
                        if (t == 2 && protocol == 4) {
                            // IPv4 address
                            var ipsplit = v.split('.');
                            if (ipsplit.length == 4) {
                                //filter[n] = btoa(String.fromCharCode(parseInt(ipsplit[0]), parseInt(ipsplit[1]), parseInt(ipsplit[2]), parseInt(ipsplit[3])));
                                //filter[n] = [ parseInt(ipsplit[0]), parseInt(ipsplit[1]), parseInt(ipsplit[2]), parseInt(ipsplit[3]) ];
                                filter[n] = rstr2hex(String.fromCharCode(parseInt(ipsplit[0]), parseInt(ipsplit[1]), parseInt(ipsplit[2]), parseInt(ipsplit[3])));
                            }
                        } else {
                            // Other values
                            filter[n] = v;
                        }
                    }
                }

                if (Q('filterprofile').value == 2) filter['FilterProfileData'] = Q('filterdata').value;
                amtstack.Create('AMT_IPHeadersFilter', filter, AddDefenseFilterOk2);
            }
        }

        function AddDefenseFilterUpdate() {
            var ok = Q('filtername').value.length > 0;
            if (ok && Q('filterprofile').value == 2) { var i = parseInt(Q('filterdata').value); ok = (i > 0 && i < 0xFFFFFFFF); }
            QE('idx_dlgOkButton', ok);
            QV('filterdatadiv', Q('filterprofile').value == 2);
            QV('ipfilterdiv', Q('filtertype').value >= 2);
        }

        function AddDefenseFilterOk2(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Ajouter un filtre de défense du système", "Impossible d'ajouter le filtre, erreur #" + status);
            } else {
                PullSystemDefense();
            }
        }

        function showFilterDetails(t, i) {
            if (xxdialogMode) return;
            var desc, filter, type, tn;
            if (t == 0) {
                tn = 'AMT_Hdr8021Filter';
                type = "Trafic Ethernet";
                filter = xxSystemDefense[tn].responses[i];
                desc = xxSystemDefenceFilterEthernetTypes[filter['HdrProtocolID8021']];
                if (!desc) desc = "Protocole Ethernet" + filter['HdrProtocolID8021'];
            } else {
                tn = 'AMT_IPHeadersFilter';
                type = "Trafic IP";
                filter = xxSystemDefense[tn].responses[i];
                desc = xxSystemDefenceFilterIPTypes[filter['HdrIPVersion']];
                if (!desc) desc = "Tous les protocoles IP" + filter['HdrIPVersion'];
            }
            var x = '';
            x += addHtmlValue("Nom", EscapeHtml(filter['Name']));
            x += addHtmlValue("Type", type);
            x += addHtmlValue("Trafic correspondant", desc);
            x += addHtmlValue("Direction", filter['FilterDirection'] == 0 ? 'Outbound / Transmit' : 'Inbound / Receive');
            if (t == 1) {
                for (var j in xxSystemDefenceFilters) {
                    if (filter[j]) {
                        var n = j, v = filter[j], t = xxSystemDefenceFilters[j];
                        if (t == 2 && v.length == 4) { v = hex2rstr(v); v = v.charCodeAt(0) + '.' + v.charCodeAt(1) + '.' + v.charCodeAt(2) + '.' + v.charCodeAt(3); }
                        if (n.startsWith('Hdr')) n = n.substring(3);
                        x += addHtmlValue("Filtre" + n, v);
                    }
                }
            }
            x += addHtmlValue("Événement sur match", (filter['ActionEventOnMatch'] == true) ? 'Yes' : 'No');
            setDialogMode(11, "Filtre Ethernet #" + filter['InstanceID'], 5, showFilterDetailsOk, x, [tn, filter]);
        }

        function showFilterDetailsOk(b, tag) {
            if (b == 2) { amtstack.Delete(tag[0], tag[1], deleteDefenseFilter); }
        }

        function deleteDefenseFilter(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Supprimer le filtre", "Impossible de supprimer le filtre, assurez-vous qu'il n'est pas utilisé.");
            } else {
                PullSystemDefense();
            }
        }

        var xxAddDefensePolicyFilters;
        function AddDefensePolicy() {
            if (xxdialogMode) return;
            xxAddDefensePolicyFilters = [];
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input id=policyname title="<policy name>:<policy precedence number>" style=float:right;width:260px maxlength=16 onkeyup=AddDefensePolicyUpdate()><div style=padding-top:4px>' + "Nom" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><select id=policytx title="' + "Action par défaut à entreprendre pour le trafic sortant" + '" style=float:right;width:133px><option value=0>Allow<option value=1>' + "Laissez tomber" + '<option value=2>' + "Autoriser, compter" +'<option value=3>' + "Drop, Count" + '<option value=4>' + "Autoriser, compter, événement" + '<option value=5>' + "Drop, Count, Event" + '</select><select id=policyrx style=float:right;width:133px title="' + "Action par défaut à entreprendre pour le trafic entrant" + '"><option value=0>' + "Autoriser" + '<option value=1>' + "Laissez tomber" + '<option value=2>' + "Autoriser, compter" + '<option value=3>' + "Drop, Count" + '<option value=4>' + "Autoriser, compter, événement" + '<option value=5>' + "Drop, Count, Event" + '</select><div style=padding-top:4px>' + "TX / RX par défaut" + '</div></div>';
            x += '<div id=policyFilters></div>';
            if (xxSystemDefense['AMT_Hdr8021Filter'].responses.length > 0 || xxSystemDefense['AMT_IPHeadersFilter'].responses.length > 0) {
                x += '<div style=height:26px;margin-top:4px><div style=float:right><select id=xfilter style=width:186px>';
                for (var i in xxSystemDefense['AMT_Hdr8021Filter'].responses) {
                    var filter = xxSystemDefense['AMT_Hdr8021Filter'].responses[i];
                    x += '<option value=' + filter['InstanceID'] + '>' + filter['Name'];
                }
                for (var i in xxSystemDefense['AMT_IPHeadersFilter'].responses) {
                    var filter = xxSystemDefense['AMT_IPHeadersFilter'].responses[i];
                    x += '<option value=' + filter['InstanceID'] + '>' + filter['Name'];
                }
                x += '</select><input id=addFilterButton type=button value=Add style=width:80px onclick=addFilterButton()></div><div style=padding-top:4px>' + "Ajouter un filtre" + '</div></div>';
            }
            setDialogMode(11, "Ajouter une stratégie de défense du système", 3, AddDefensePolicyOk, x);
            AddDefensePolicyUpdate();
        }

        function addFilterButton() {
            if (xxAddDefensePolicyFilters.indexOf(Q('xfilter').value) >= 0) return;
            xxAddDefensePolicyFilters.push(Q('xfilter').value);
            AddDefensePolicyUpdate();
        }

        function removeFilterButton(h) {
            xxAddDefensePolicyFilters.splice(h, 1);
            AddDefensePolicyUpdate();
        }

        function AddDefensePolicyUpdate() {
            var ok = Q('policyname').value.split(':')[0].length > 0;
            QE('idx_dlgOkButton', ok);
            if (xxAddDefensePolicyFilters.length == 0) {
                QH('policyFilters', '<br><i>' + "Cette politique ne contient aucun filtre." + '</i><br><br>');
            } else {
                var x = '';
                for (var i in xxAddDefensePolicyFilters) {
                    x += '<div class=itemBar style=margin-right:0><div style=float:right>' + AddButton2("Retirer", 'removeFilterButton(' + i + ')') + '</div><div style=padding-top:3px;max-width:260px;overflow:hidden><b>' + GetFilterById(xxAddDefensePolicyFilters[i])['Name'] + '</b></div></div>';
                }
                QH('policyFilters', x);
            }
        }

        // TODO: Once loaded, we could make a table of "handle -> filter" where both filter types are mixed-in. Could make things simpler/smaller?
        // We would only have one table to loop instead of two at a few places. This function would be removed completely.
        function GetFilterById(h) {
            for (var i in xxSystemDefense['AMT_Hdr8021Filter'].responses) { var filter = xxSystemDefense['AMT_Hdr8021Filter'].responses[i]; if (filter['InstanceID'] == h) return filter; }
            for (var i in xxSystemDefense['AMT_IPHeadersFilter'].responses) { var filter = xxSystemDefense['AMT_IPHeadersFilter'].responses[i]; if (filter['InstanceID'] == h) return filter; }
        }

        function AddDefensePolicyOk() {
            var tx = Q('policytx').value;
            var rx = Q('policyrx').value;
            var pri = 0;
            var n = Q('policyname').value.split(':');
            if (n.length == 2) pri = parseInt(n[1]);
            var filter = { 'InstanceID ': 0, 'PolicyName': n[0], 'PolicyPrecedence': pri, 'TxDefaultCount': (tx > 1), 'TxDefaultDrop': (tx % 2 == 1), 'TxDefaultMatchEvent': (tx > 3), 'RxDefaultCount': (rx > 1), 'RxDefaultDrop': (rx % 2 == 1), 'RxDefaultMatchEvent': (rx > 3) };
            if (xxAddDefensePolicyFilters.length > 0) filter['FilterCreationHandles'] = xxAddDefensePolicyFilters;
            amtstack.Create('AMT_SystemDefensePolicy', filter, AddDefensePolicyOk2);
        }

        function AddDefensePolicyOk2(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Ajouter une stratégie de défense du système", "Impossible d'ajouter la stratégie, erreur #" + status);
            } else {
                PullSystemDefense();
            }
        }

        function showPolicyDetails(i) {
            if (xxdialogMode) return;
            var policy = xxSystemDefense['AMT_SystemDefensePolicy'].responses[i];
            var x = '';
            x += addHtmlValue("Nom", EscapeHtml(policy['PolicyName']));
            if (policy['PolicyPrecedence'] != 0) x += addHtmlValue("Priorité", policy['PolicyPrecedence']);

            var action = (policy['TxDefaultDrop'] == true) ? "Laissez tomber" : "Autoriser";
            if (policy['TxDefaultCount'] == true) action += ", Compter";
            if (policy['TxDefaultMatchEvent'] == true) action += ", Un événement";
            x += addHtmlValue("Action TX par défaut", action);

            action = (policy['RxDefaultDrop'] == true) ? 'Drop' : 'Allow';
            if (policy['RxDefaultCount'] == true) action += ', Count';
            if (policy['RxDefaultMatchEvent'] == true) action += ', Event';
            x += addHtmlValue("Action RX par défaut", action);

            if (policy['FilterCreationHandles']) { for (var i in policy['FilterCreationHandles']) { x += addHtmlValue("Filtre #" + (+i + 1), GetFilterById(policy['FilterCreationHandles'][i])['Name']); } }

            setDialogMode(11, format("Politique #", policy['InstanceID'].substring(20)), 5, showPolicyDetailsOk, x, policy);
        }

        function showPolicyDetailsOk(b, tag) {
            if (b == 2) { amtstack.Delete('AMT_SystemDefensePolicy', tag, deleteDefensePolicy); }
        }

        function deleteDefensePolicy(stack, name, responses, status) {
            if (status != 200) {
                messagebox("Supprimer la politique", "Impossible de supprimer la stratégie, assurez-vous qu'elle n'est pas utilisée.");
            } else {
                PullSystemDefense();
            }
        }

// ###END###{SystemDefense}

// ###BEGIN###{NetworkSettings}
// ###BEGIN###{Wireless}

        //
        // WIRELESS SETTINGS PANEL
        //

        var xxWireless;
        function PullWireless() {
            amtFirstPull |= 2;
            try { if (amtwirelessif == -1) return; } catch (e) { } // If the wireless adapter has no MAC, don't show this.
            // ###BEGIN###{!NetAuth}
            amtstack.BatchEnum('', ['*CIM_WiFiPortCapabilities', '*CIM_WiFiPort', '*CIM_WiFiEndpoint', 'CIM_WiFiEndpointSettings', '*AMT_WiFiPortConfigurationService'], processWireless);
            // ###END###{!NetAuth}
            // ###BEGIN###{NetAuth}
            amtstack.BatchEnum('', ['*CIM_WiFiPortCapabilities', '*CIM_WiFiPort', '*CIM_WiFiEndpoint', 'CIM_WiFiEndpointSettings', '*AMT_WiFiPortConfigurationService', 'CIM_IEEE8021xSettings'], processWireless);
            // ###END###{NetAuth}
        }

        function wifiRefresh() { if (!xxdialogMode) PullWireless(); }

        var xxWifiState = { 3: "désactivé", 32768: "Activé dans S0", 32769: "Activé dans S0, Sx / AC" };
        var xxRadioState = 	{ 2: "Allumé, connecté", 3: "De", 6: "Activé, déconnecté" };
        var xxWifiAuthenticationMethod = { 1: "Autre", 2: "Ouvert", 3: "Clé partagée", 4: "WPA PSK", 5: "WPA IEEE 802.1x", 6: "WPA2 PSK", 7: "WPA2 IEEE 802.1x", 32768: "WPA3 SAE IEEE 802.1x", 32769: "WPA3 OWE IEEE 802.1x" };
        var xxWifiEncryptionMethod = { 1: "Autre", 2: "WEP", 3: "TKIP-RC4", 4: "CCMP-AES", 5: "Aucun" }; // For 2 & 5, AuthenticationMethod must be 2 or 3. For 3 & 4 AuthenticationMethod must be 4,5,6 or 7

        function processWireless(stack, name, responses, status) {
            if (status == 200) { xxWireless = responses; } else { xxWireless = undefined; }
            updateSystemStatus();
            showWirelessInfo();
        }

        function showWirelessInfo() {
            if (!xxWireless) return;
            var i, j, s = '', sc, x = '<br><h2>' + "Profils sans fil" + '</h2>';
            if (!(xxWireless['CIM_WiFiPortCapabilities'].response)) return;

            // Show WIFI profiles sorted by priority
            x += TableStart2();
            x += '<tr><td class=r2 style=padding-left:15px><br>' + "Profils sans fil qu'Intel&reg; AMT utilisera pour la connectivité réseau." + '<br><br>';
            s = 0;
            for(i = 0; i < 256; i++) {
                for (j in xxWireless['CIM_WiFiEndpointSettings'].responses) {
                    sc = xxWireless['CIM_WiFiEndpointSettings'].responses[j];
                    if (sc['AuthenticationMethod'] == 1) continue; // Skip "Endpoint User Settings"
                    if (sc['Priority'] == i) {
                        var details = '';
                        // ###BEGIN###{NetAuth}
                        var netAuthProfile = null, netAuthProtocols = ['EAP-TLS', 'EAP-TTLS/MSCHAPv2', 'PEAPv0/EAP-MSCHAPv2', 'PEAPv1/EAP-GTC', 'EAP-FAST/MSCHAPv2', 'EAP-FAST/GTC', 'EAP-MD5', 'EAP-PSK', 'EAP-SIM', 'EAP-AKA', 'EAP-FAST/TLS'];
                        if (xxWireless['CIM_IEEE8021xSettings'].responses) {
                            for (var k in xxWireless['CIM_IEEE8021xSettings'].responses) {
                                if (xxWireless['CIM_IEEE8021xSettings'].responses[k]['ElementName'] == sc['ElementName']) { netAuthProfile = xxWireless['CIM_IEEE8021xSettings'].responses[k]; }
                            }
                        }
                        if (netAuthProfile) { details = ', ' + netAuthProtocols[netAuthProfile['AuthenticationProtocol']]; }
                        // ###END###{NetAuth}
                        x += '<div class=itemBar onclick=showWifiDetails(' + j + ')><div style=float:right>' + EscapeHtml(sc['SSID']) + ', ' + xxWifiAuthenticationMethod[sc['AuthenticationMethod']] + ', ' + xxWifiEncryptionMethod[sc['EncryptionMethod']] + details + ' &nbsp; ';
                        if (xxAccountAdminName) x += AddButton2("Retirer", 'wifiRemoveButton(\"' + j + '\")');
                        x += '</div><div style=padding-top:3px><b>' + EscapeHtml(sc['ElementName']) + '</b></div></div>';
                        s++;
                    }
                }
            }
            if (s == 0) x += '<i>' + "Aucun profil sans fil présent" + '</i><br>';

            // End of table
            x += '<br><td class=r2>';
            if (xxAccountAdminName) x += TableEnd(AddButton("Nouveau profile", 'showWifiNewProfile()')); else x += TableEnd('');
            QH('id_TableWifi2', x + '<br>');
        }
        
        function showWifiStateDlg() {
            if (xxdialogMode) return;
            var s = '';
            for (var i in xxWifiState) { s += '<label><input type=radio name=d11 id=wl' + i + ' value=' + i + ' ' + ((xxWireless['CIM_WiFiPort'].response['EnabledState'] == i)?'checked':'') + '>' + xxWifiState[i] + '</label><br>'; }
            setDialogMode(11, "État sans fil", 3, wifiStateDlg, s);
        }

        function wifiStateDlg() { amtstack.CIM_WiFiPort_RequestStateChange( document.querySelector('input[name=d11]:checked').value, null, function() { amtstack.Get('CIM_WiFiPort', function(stack, name, response, status) { if (status == 200) { xxWireless['CIM_WiFiPort'].response = response.Body; showWirelessInfo(); } } ); } ); }

        function showWifiSyncDlg() {
            if (xxdialogMode) return;
            var s = '';
            s += '<label><input type=radio name=d11 id=wl0 value=0 ' + ((xxWireless['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 0) ? 'checked' : '') + '>' + "désactivé" + '</label><br>';
            s += '<label><input type=radio name=d11 id=wl0 value=1 ' + ((xxWireless['AMT_WiFiPortConfigurationService'].response['localProfileSynchronizationEnabled'] == 1) ? 'checked' : '') + '>' + "Activée" + '</label><br>';
            setDialogMode(11, "Local Profile Sync", 3, showWifiSyncDlgEx, s);
        }

        function showWifiSyncDlgEx() {
            var k = Clone(xxWireless['AMT_WiFiPortConfigurationService'].response);
            k['localProfileSynchronizationEnabled'] = document.querySelector('input[name=d11]:checked').value;
            amtstack.Put('AMT_WiFiPortConfigurationService', k, function () { amtstack.Get('AMT_WiFiPortConfigurationService', function (stack, name, response, status) { if (status == 200) { xxWireless['AMT_WiFiPortConfigurationService'].response = response.Body; showWirelessInfo(); } }); });
        }
        
        function showUefiWifiCoExDlg() {
            if (xxdialogMode) return;
            var s = '';
            s += '<label><input type=radio name=d12 value=0 ' + ((xxWireless['AMT_WiFiPortConfigurationService'].response['UEFIWiFiProfileShareEnabled'] == false)?'checked':'') + '>Disabled</label><br>'; 
            s += '<label><input type=radio name=d12 value=1 ' + ((xxWireless['AMT_WiFiPortConfigurationService'].response['UEFIWiFiProfileShareEnabled'] == true)?'checked':'') + '>Enabled</label><br>'; 
            setDialogMode(11, "UEFI Wifi CoEx Profile Sharing", 3, UefiWifiCoExDlg, s);
        }
        
        function UefiWifiCoExDlg() {
            var wifiportcfgsvc = Clone(xxWireless['AMT_WiFiPortConfigurationService'].response);
            wifiportcfgsvc["UEFIWiFiProfileShareEnabled"]=document.querySelector('input[name=d12]:checked').value;
            amtstack.Put('AMT_WiFiPortConfigurationService', wifiportcfgsvc, function(stack, name, responses, status) {if (status == 200) {PullWireless()}})
        }

        function showWifiDetails(h) {
            if (xxdialogMode) return;
            var i, sc = xxWireless['CIM_WiFiEndpointSettings'].responses[h], x = '<div style=text-align:left>';
            x += addHtmlValue("Nom de profil", EscapeHtml(sc['ElementName']));
            x += addHtmlValue("SSID", EscapeHtml(sc['SSID']));
            x += addHtmlValue("Authentification", xxWifiAuthenticationMethod[sc['AuthenticationMethod']]);
            x += addHtmlValue("Chiffrement", xxWifiEncryptionMethod[sc['EncryptionMethod']]);
            x += addHtmlValue("Priorité", sc['Priority']);
            // ###BEGIN###{NetAuth}
            var netAuthProfile = null, netAuthProtocols = ['EAP-TLS', 'EAP-TTLS/MSCHAPv2', 'PEAPv0/EAP-MSCHAPv2', 'PEAPv1/EAP-GTC', 'EAP-FAST/MSCHAPv2', 'EAP-FAST/GTC', 'EAP-MD5', 'EAP-PSK', 'EAP-SIM', 'EAP-AKA', 'EAP-FAST/TLS'];
            if (xxWireless['CIM_IEEE8021xSettings'].responses) {
                for (var k in xxWireless['CIM_IEEE8021xSettings'].responses) {
                    if (xxWireless['CIM_IEEE8021xSettings'].responses[k]['ElementName'] == sc['ElementName']) { netAuthProfile = xxWireless['CIM_IEEE8021xSettings'].responses[k]; }
                }
            }
            if (netAuthProfile) {
                x += '<div style="width:100%;border-bottom:1px solid #000;margin-bottom:5px;margin-top:5px">802.11x</div>'
                x += addHtmlValue("Authentification", netAuthProtocols[netAuthProfile['AuthenticationProtocol']]);
                if (netAuthProfile['Domain']) { x += addHtmlValue("Domain", EscapeHtml(netAuthProfile['Domain'])); }
                if (netAuthProfile['Username']) { x += addHtmlValue("Nom d'utilisateur", EscapeHtml(netAuthProfile['Username'])); }
            }
            // ###END###{NetAuth}
            x += '</div>';
            messagebox("Profil sans fil", x);
        }

        function wifiRemoveButton(h) {
            if (xxdialogMode) return;
            var sc = xxWireless['CIM_WiFiEndpointSettings'].responses[h];
            QH('id_dialogMessage', format("Supprimer le profil sans fil \"{0}\"?", sc['ElementName']));
            setDialogMode(1, "Profil sans fil", 3, function () { removeWifiButtonEx(h) });
        }

        function removeWifiButtonEx(h) {
            var sc = xxWireless['CIM_WiFiEndpointSettings'].responses[h];
            amtstack.Delete('CIM_WiFiEndpointSettings', { InstanceID: sc['InstanceID'] }, removeWifiEntryResponse, 0, 1);
        }

        function removeWifiEntryResponse(stack, name, response, status, tag) {
            if (methodcheck(response)) return;
            // ###BEGIN###{!NetAuth}
            amtstack.BatchEnum('', ['CIM_WiFiEndpointSettings'], function (stack, name, responses, status) {
                if (status == 200) {
                    xxWireless['CIM_WiFiEndpointSettings'].responses = responses['CIM_WiFiEndpointSettings'].responses;
                    showWirelessInfo();
                }
            });
            // ###END###{!NetAuth}
            // ###BEGIN###{NetAuth}
            amtstack.BatchEnum('', ['CIM_WiFiEndpointSettings', 'CIM_IEEE8021xSettings'], function (stack, name, responses, status) {
                if (status == 200) {
                    xxWireless['CIM_WiFiEndpointSettings'].responses = responses['CIM_WiFiEndpointSettings'].responses;
                    xxWireless['CIM_IEEE8021xSettings'].responses = responses['CIM_IEEE8021xSettings'].responses;
                    showWirelessInfo();
                }
            });
            // ###END###{NetAuth}
        }

        function showWifiNewProfile() {
            if (xxdialogMode) return;
            var x = '';
            for (i = 1; i < 256; i++) {
                var t = 1;
                for (j in xxWireless['CIM_WiFiEndpointSettings'].responses) { if (xxWireless['CIM_WiFiEndpointSettings'].responses[j]['Priority'] == i) t = 0; }
                if (t) { x += '<option value='+ i +'>'+ i; } // Option is a tag that is self closing.
            }
            QH('idx_d12pri', x);

            // ###BEGIN###{NetAuth}
            // Set certificates
            var clientcertoptions = '<option value=-1>' + EscapeHtml("Aucun") + '</option>', servercertoptions = '<option value=-1>' + EscapeHtml("Aucun") + '</option>';
            for (var i in xxCertificates) {
                if (xxCertificates[i].TrustedRootCertficate) {
                    servercertoptions += '<option value="' + i + '">' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</option>';
                } else if (xxCertificates[i].XPrivateKey) {
                    clientcertoptions += '<option value="' + i + '">' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</option>';
                }
            }
            QH('idx_d12clientcert', clientcertoptions);
            QH('idx_d12servercert', servercertoptions);
            // ###END###{NetAuth}

            var authOptions = '';
            // ###BEGIN###{NetAuth}
            authOptions += '<option value=32769>' + "WPA3 OWE IEEE 802.1x" + '</option>';
            authOptions += '<option value=32768>' + "WPA3 SAE IEEE 802.1x" + '</option>';
            authOptions += '<option value=7>' + "WPA2 IEEE 802.1x" + '</option>';
            authOptions += '<option value=5>' + "WPA IEEE 802.1x" + '</option>';
            // ###END###{NetAuth}
            authOptions += '<option value=6>' + "WPA2 PSK" + '</option>';
            authOptions += '<option value=4>' + "WPA PSK" + '</option>';
            QH('idx_d12auth', authOptions);

            idx_d12auth.value = 6;
            idx_d12enc.value = 4;
            idx_d12name.value = idx_d12ssid.value = idx_d12password1.value = idx_d12password2.value = '';

            setDialogMode(12, "Ajouter un profil sans fil", 3, function () { addWifiProfile() });
            updateWifiDialog();
        }

        function addWifiProfile() {
            var sc, netAuthSettingsClientCert, netAuthSettingsServerCaCert;
            var v = {
                '__parameterType': 'instance',
                '__namespace': amtstack.CompleteName('CIM_WiFiEndpointSettings'),
                'ElementName': idx_d12name.value,
                'InstanceID': 'Intel(r) AMT:WiFi Endpoint Settings ' + idx_d12name.value,
                'AuthenticationMethod': idx_d12auth.value,
                'EncryptionMethod': idx_d12enc.value,
                'SSID': idx_d12ssid.value,
                'Priority': idx_d12pri.value
            };
            if ((idx_d12auth.value == 4) || (idx_d12auth.value == 6)) { v['PSKPassPhrase'] = idx_d12password1.value; }
            // ###BEGIN###{NetAuth}
            if ((idx_d12auth.value == 5) || (idx_d12auth.value == 7) || (idx_d12auth.value == 32768) || (idx_d12auth.value == 32769)) {
                sc = {
                    '__parameterType': 'instance',
                    '__namespace': amtstack.CompleteName('CIM_IEEE8021xSettings'),
                    'ElementName': '8021x-' + idx_d12name.value,
                    'InstanceID': '8021x-' + idx_d12name.value,
                    'ActiveInS0': (Q('idx_d12activeins0').value == 1),
                    'AuthenticationProtocol': Q('idx_d12protocol').value
                };
                if (Q('idx_d12roamingidentity').value != '') { sc['RoamingIdentity'] = Q('idx_d12roamingidentity').value; }
                if (Q('idx_d12servername').value != '') { sc['ServerCertificateName'] = Q('idx_d12servername').value; sc['ServerCertificateNameComparison'] = Q('idx_d12servernamecompare').value; }
                if (Q('idx_d12username').value != '') { sc['Username'] = Q('idx_d12username').value; }
                if (Q('idx_d12password').value != '') { sc['Password'] = Q('idx_d12password').value; }
                if (Q('idx_d12domain').value != '') { sc['Domain'] = Q('idx_d12domain').value; }
                if (Q('idx_d12protocol').value > 3) { sc['ProtectedAccessCredential'] = Q('idx_d12pac').value; sc['PACPassword'] = Q('idx_d12pacpassword').value; }
                if (parseInt(Q('idx_d12clientcert').value) >= 0) { netAuthSettingsClientCert = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d12clientcert').value)]['InstanceID'] + '</Selector></SelectorSet></ReferenceParameters>'; }
                if (parseInt(Q('idx_d12servercert').value) >= 0) { netAuthSettingsServerCaCert = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d12servercert').value)]['InstanceID'] + '</Selector></SelectorSet></ReferenceParameters>'; }
            }
            // ###END###{NetAuth}

            console.log('wifiepsettinginput', JSON.sstringify(v, null, 2));
            console.log('netAuthProfile', JSON.sstringify(sc, null, 2));
            console.log('netAuthSettingsClientCert', netAuthSettingsClientCert);
            console.log('netAuthSettingsServerCaCert', netAuthSettingsServerCaCert);

            amtstack.AMT_WiFiPortConfigurationService_AddWiFiSettings(
				{
				    '__parameterType': 'reference',
				    '__resourceUri': amtstack.CompleteName('CIM_WiFiEndpoint'),
				    'Name': 'WiFi Endpoint 0'
				}, v,
				sc, netAuthSettingsClientCert, netAuthSettingsServerCaCert, removeWifiEntryResponse
			);
        }

        function updateWifiDialog() {
            var r = true;
            var a = idx_d12auth.value;
            var e = idx_d12enc.value;
            //QV('id_d12e2', a < 4);
            //QV('id_d12e3', a > 3);
            //QV('id_d12e4', a > 3);
            //QV('id_d12e5', a < 4);
            if (a < 4 && (e == 3 || e == 4)) { idx_d12enc.value = 2; }
            if (a > 3 && (e == 2 || e == 5)) { idx_d12enc.value = 3; }
            if ((a == 32768) || (a == 32769)) { idx_d12enc.value = 4; }
            QV('idx_d12pass', (a == 4) || (a == 6));
            QV('idx_d12netauth', (a == 5) || (a == 7) || (a == 32768) || (a == 32769));

            // Check if there is already a profile with this name
            for (var j in xxWireless['CIM_WiFiEndpointSettings'].responses) { if (xxWireless['CIM_WiFiEndpointSettings'].responses[j]['ElementName'] == idx_d12name.value) { r = false; } }
            if ((idx_d12name.value.length == 0) && (idx_d12ssid.value.length == 0)) { r = false; }
            if (((a == 4) || (a == 6)) && ((idx_d12password1.value.length < 8) || (idx_d12password1.value.length > 63) || (idx_d12password1.value != idx_d12password2.value))) { r = false; }

            QE('idx_dlgOkButton', r);

            // ###BEGIN###{NetAuth}
            updateNetAuthDialog();
            // ###END###{NetAuth}
        }

        // ###BEGIN###{NetAuth}
        function updateNetAuth2Dialog() {
            QV('idx_d12servernamecomparediv', (Q('idx_d12servernamediv').value != ''));
            QV('idx_d12pacdiv', (Q('idx_d12protocol').value > 3));
            QV('idx_d12pacpassworddiv', (Q('idx_d12protocol').value > 3));
        }
        // ###END###{NetAuth}

// ###END###{Wireless}
// ###BEGIN###{NetAuth}

        //
        // 802.1x SETTINGS
        //

        function editNetAuthProfile() {
            if (xxdialogMode) return;

            // Set certificates
            var clientcertoptions = '<option value=-1>' + EscapeHtml("Aucun") + '</option>', servercertoptions = '<option value=-1>' + EscapeHtml("Aucun") + '</option>';
            for (var i in xxCertificates) {
                if (xxCertificates[i].TrustedRootCertficate) {
                    servercertoptions += '<option value="' + i + '">' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</option>';
                } else if (xxCertificates[i].XPrivateKey) {
                    clientcertoptions += '<option value="' + i + '">' + EscapeHtml(xxCertificates[i].XSubject['CN']) + '</option>';
                }
            }
            QH('idx_d27clientcert', clientcertoptions);
            QH('idx_d27servercert', servercertoptions);

            // Set profile
            var sc = amtsysstate['AMT_8021XProfile'].responses.Body;
            Q('idx_d27enabled').value = sc['Enabled'] ? 1 : 0;
            Q('idx_d27activeins0').value = (sc['ActiveInS0'] ? 1 : 0);
            Q('idx_d27pxetimeout').value = sc['PxeTimeout'];
            if (sc['Enabled']) {
                Q('idx_d27protocol').value = sc['AuthenticationProtocol'];
                Q('idx_d27roamingidentity').value = sc['RoamingIdentity'] ? sc['RoamingIdentity'] : '';
                Q('idx_d27servername').value = sc['ServerCertificateName'] ? sc['ServerCertificateName'] : '';
                Q('idx_d27servernamecompare').value = sc['ServerCertificateNameComparison'] ? sc['ServerCertificateNameComparison'] : 0;
                Q('idx_d27username').value = sc['Username'] ? sc['Username'] : '';
                Q('idx_d27password').value = sc['Password'] ? sc['Password'] : '';
                Q('idx_d27domain').value = sc['Domain'] ? sc['Domain'] : '';
                Q('idx_d27pac').value = sc['ProtectedAccessCredential'] ? sc['ProtectedAccessCredential'] : '';
                Q('idx_d27pacpassword').value = sc['PACPassword'] ? sc['PACPassword'] : '';
                var scInstanceId = -1, ccInstanceId = -1;
                if (sc['ServerCertificateIssuer']) { scInstanceId = sc['ServerCertificateIssuer']['ReferenceParameters']['SelectorSet']['Selector']['Value']; }
                if (sc['ClientCertificate']) { ccInstanceId = sc['ClientCertificate']['ReferenceParameters']['SelectorSet']['Selector']['Value']; }
                for (var i in xxCertificates) {
                    if (xxCertificates[i]['InstanceID'] == scInstanceId) { Q('idx_d27servercert').value = i; }
                    if (xxCertificates[i]['InstanceID'] == ccInstanceId) { Q('idx_d27clientcert').value = i; }
                }
            }
            setDialogMode(27, "802.1x Profile", 3, function () { setNetAuthProfile() });
            updateNetAuthDialog();
        }

        function updateNetAuthDialog() {
            QV('idx_d27protocoldiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27servernamediv', Q('idx_d27enabled').value == 1);
            QV('idx_d27servernamecomparediv', (Q('idx_d27enabled').value == 1) && (Q('idx_d27servername').value != ''));
            QV('idx_d27domaindiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27usernamediv', Q('idx_d27enabled').value == 1);
            QV('idx_d27passworddiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27roamingidentitydiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27pacdiv', (Q('idx_d27enabled').value == 1) && (Q('idx_d27protocol').value > 3));
            QV('idx_d27pacpassworddiv', (Q('idx_d27enabled').value == 1) && (Q('idx_d27protocol').value > 3));
            QV('idx_d27clientcertdiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27servercertdiv', Q('idx_d27enabled').value == 1);
            QV('idx_d27activeins0div', Q('idx_d27enabled').value == 1);
            QV('idx_d27pxetimeoutdiv', Q('idx_d27enabled').value == 1);
        }

        function setNetAuthProfile() {
            var sc = Clone(amtsysstate['AMT_8021XProfile'].responses.Body);
            sc['Enabled'] = (Q('idx_d27enabled').value == 1);
            if (sc['Enabled']) {
                sc['ActiveInS0'] = (Q('idx_d27activeins0').value == 1);
                sc['AuthenticationProtocol'] = Q('idx_d27protocol').value;
                if (Q('idx_d27roamingidentity').value != '') { sc['RoamingIdentity'] = Q('idx_d27roamingidentity').value; } else { delete sc['RoamingIdentity']; }
                if (Q('idx_d27servername').value != '') {
                    sc['ServerCertificateName'] = Q('idx_d27servername').value;
                    sc['ServerCertificateNameComparison'] = Q('idx_d27servernamecompare').value;
                } else {
                    delete sc['ServerCertificateName'];
                    delete sc['ServerCertificateNameComparison'];
                }
                if (Q('idx_d27username').value != '') { sc['Username'] = Q('idx_d27username').value; } else { delete sc['Username']; }
                if (Q('idx_d27password').value != '') { sc['Password'] = Q('idx_d27password').value; } else { delete sc['Password']; }
                if (Q('idx_d27domain').value != '') { sc['Domain'] = Q('idx_d27domain').value; } else { delete sc['Domain']; }
                if (Q('idx_d27protocol').value > 3) {
                    sc['ProtectedAccessCredential'] = Q('idx_d27pac').value;
                    sc['PACPassword'] = Q('idx_d27pacpassword').value;
                } else {
                    delete sc['ProtectedAccessCredential'];
                    delete sc['PACPassword'];
                }
                if (parseInt(Q('idx_d27clientcert').value) >= 0) { sc['ClientCertificate'] = '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d27clientcert').value)]['InstanceID'] + '</w:Selector></w:SelectorSet></a:ReferenceParameters>'; } else { delete sc['ClientCertificate']; }
                if (parseInt(Q('idx_d27servercert').value) >= 0) { sc['ServerCertificateIssuer'] = '<a:Address>/wsman</a:Address><a:ReferenceParameters><w:ResourceURI>' + amtstack.CompleteName('AMT_PublicKeyCertificate') + '</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">' + xxCertificates[parseInt(Q('idx_d27servercert').value)]['InstanceID'] + '</w:Selector></w:SelectorSet></a:ReferenceParameters>'; } else { delete sc['ServerCertificateIssuer']; }
                sc['PxeTimeout'] = Q('idx_d27pxetimeout').value;
            }
            amtstack.Put('AMT_8021XProfile', sc, setNetAuthProfileEx);
        }

        function setNetAuthProfileEx(stack, name, response, status) {
            if (status == 200) {
                amtsysstate['AMT_8021XProfile'].responses.Body = amtsysstate['AMT_8021XProfile'].response = response.Body;
                updateSystemStatus();
            } else {
                if (response.Header['WsmanError']) {
                    messagebox("802.1x Error", response.Header['WsmanError'].replace(/_/g, ' '));
                } else {
                    messagebox("802.1x Error", "Error, Status = " + status);
                }
            }
        }

// ###END###{NetAuth}
// ###END###{NetworkSettings}

// ###BEGIN###{HardwareInfo}
        //
        // HARDWARE INFORMATION PANEL
        //

        function PullHardware() {
            amtstack.BatchEnum('', ['*CIM_ComputerSystemPackage', 'CIM_SystemPackaging', '*CIM_Chassis', 'CIM_Chip', '*CIM_Card', '*CIM_BIOSElement', 'CIM_Processor', 'CIM_PhysicalMemory', 'CIM_MediaAccessDevice', 'CIM_PhysicalPackage', '*CIM_Battery'], processHardware);
            amtFirstPull |= 1; // Set the hardware info bit on, indicates we are pulling this information.
        }

        // http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
        var DMTFCPUStatus = ["Inconnue", "Activée", "Désactivé par l'utilisateur", "Désactivé par le BIOS (erreur POST)", "Tourner au ralenti", "Autre"];
        var DMTFMemType = ["Inconnue", "Autre", "DRACHME", "DRAM synchrone", "Cache DRAM", "EDO", "EDRAM", "VRAM", "SRAM", "RAM", "ROM", "Éclat", "EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM", "SDRAM", "SGRAM", "RDRAM", "DDR", "DDR-2", "BRAM", "FB-DIMM", "DDR3", "FBD2", "DDR4", "LPDDR", "LPDDR2", "LPDDR3", "LPDDR4"];
        var DMTFMemFormFactor = ['', "Autre","Inconnue","SIMM","siroter","Puce","TREMPER","ZIP","Carte propriétaire","DIMM","TSOP","Rangée de jetons","RIMM","SODIMM","SRIMM","FB-DIM"];
        var DMTFProcFamilly = { // Page 46 of DMTF document
            191: "Processeur Intel&reg; Core &trade; 2 Duo",
            192: "Processeur Intel&reg; Core &trade; 2 Solo",
            193: "Processeur Intel&reg; Core &trade; 2 Extreme",
            194: "Processeur Intel&reg; Core &trade; 2 Quad",
            195: "Processeur mobile Intel&reg; Core &trade; 2 Extreme",
            196: "Processeur mobile Intel&reg; Core &trade; 2 Duo",
            197: "Processeur mobile Intel&reg; Core &trade; 2 Solo",
            198: "Processeur Intel&reg; Core &trade; i7",
            199: "Processeur Intel&reg; Celeron&reg; double cœur" };

        var HardwareInventory;
        function processHardware(stack, name, responses, status) {
            if (status != 200) return;

            var i, x = '<table class=log1 cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px>';
            HardwareInventory = responses;
            QV('go2', true); // Show "Hardware Information" on left panel

            // ###BEGIN###{!FileSaver}
            x += TableEnd('<div>&nbsp;' + AddRefreshButton('PullHardware(1)') + " Les informations sur le matériel sont collectées au démarrage du système.");
            // ###END###{!FileSaver}
            // ###BEGIN###{FileSaver}
            x += TableEnd('<div>&nbsp;' + AddRefreshButton('PullHardware(1)') + AddButton("Sauver...", 'SaveHardwareLog()') + " Les informations sur le matériel sont collectées au démarrage du système.");
            // ###END###{FileSaver}

            var ba = responses['CIM_Chassis'].response;
            var bb = responses['CIM_Card'].response;
            var v = responses['CIM_BIOSElement'].response['SoftwareElementID'];
            
            x += '<br><h2>' + "Plate-forme" + '</h2>';
            x += FullTable({"Modèle informatique":ba['Model'], "Fabricant":ba['Manufacturer'], "Version":ba['Version'], "Numéro de série":ba['SerialNumber'], "ID système":guidToStr(responses['CIM_SystemPackaging'].responses[0]['PlatformGUID']).toLowerCase()}, '');

            x += '<br><h2>' + "Plinthe" + '</h2>';
            x += FullTable({"Fabricant":bb['Manufacturer'], "Nom du produit":bb['Model'], "Version":bb['Version'], "Numéro de série":bb['SerialNumber'], "Étiquette d'inventaire":bb['Tag'], "Remplaçable?":(bb['CanBeFRUed']==true)?'Yes':'No' },'');
            
            x += '<br><h2>' + "BIOS" + '</h2>';
            x += FullTable({"Vendeur":responses['CIM_BIOSElement'].response['Manufacturer'], "Version":v, "Date de sortie":new Date(responses['CIM_BIOSElement'].response['ReleaseDate']['Datetime']).toLocaleDateString('en', {timeZone:'UTC'})},'');
            
            x += '<br>';
            for (i in responses['CIM_Processor'].responses) {
                var p = responses['CIM_Processor'].responses[i];
                var q = responses['CIM_Chip'].responses[i]; // This is a shortcut, we assume that the first entries in CIM_Chip are the processors, in the same order.
                x += '<h2>' + "Processeur" + ' ' + (parseInt(i) + 1) + '</h2>';
                x += FullTable({"Fabricant":trademarks(q['Manufacturer']), "Famille":DMTFProcFamilly[p['Family']], "Version":trademarks(q['Version']), "Vitesse de prise maximale":p['MaxClockSpeed'] + " MHz", "Statut":DMTFCPUStatus[p['CPUStatus']]},'');
            }
            x += '<br>';

            for (i in responses['CIM_PhysicalMemory'].responses) {
                var m = responses['CIM_PhysicalMemory'].responses[i];
                x += '<h2>' + "Module de mémoire" + ' ' + (+i + 1) + '</h2>';
                x += FullTable({"Étiquette de banque":m['BankLabel'], "Fabricant":m['Manufacturer'], "Numéro de série":m['SerialNumber'], "Taille":parseInt(m['Capacity'] / 0x100000) + " MB", "Facteur de forme":DMTFMemFormFactor[m['FormFactor']], "Type":DMTFMemType[m['MemoryType']], "Étiquette d'inventaire":m['Tag'], "Numéro d'article":m['PartNumber']},'');
            }
            x += '<br>';

            for (i in responses['CIM_MediaAccessDevice'].responses) {
                var m = responses['CIM_MediaAccessDevice'].responses[i];
                var n = responses['CIM_PhysicalPackage'].responses[+i + 1]; // This is a shortcut, we assume CIM_PhysicalPackage is the same as CIM_MediaAccessDevice except for the first entry.
                x += '<h2>' + "Supports de stockage" + ' ' + (parseInt(i) + 1) + '</h2>';
                x += FullTable({"Modèle":n['Model'],"Numéro de série":(n['SerialNumber']==''?'Unknown':n['SerialNumber']), "Taille":parseInt(Math.round(m['MaxMediaSize'] * 1000 / 0x100000)) + " MB"},'');
            }
            x += '<br>';

            if (responses['CIM_Battery'].response != null) {
                var battInfo = null;
                for (i in responses['CIM_PhysicalPackage'].responses) { if (responses['CIM_PhysicalPackage'].responses[i].PackageType == 11) { battInfo = responses['CIM_PhysicalPackage'].responses[i]; } }
                if (battInfo != null) {
                    x += '<h2>' + "Battery" + '</h2>';
                    var battdate = new Date(battInfo['ManufactureDate']['Datetime']).toDateString()
                    var batttype = ["Autre", "Inconnue", "Lead Acid", "Nickel Cadmium", "Nickel Metal Hydride", "Lithium-ion", "Zinc air", "Lithium Polymer"][responses['CIM_Battery'].response['Chemistry']];
                    var batt = { "Device name": responses['CIM_Battery'].response['DeviceID'], "Fabricant": battInfo['Manufacturer'], "Manufacture date": battdate, "Numéro de série": battInfo['SerialNumber'], "Type": batttype, "Design capacity": responses['CIM_Battery'].response['DesignCapacity'] + ' ' + "mWatt-hours", "Design voltage": responses['CIM_Battery'].response['DesignVoltage'] + ' ' + "mVolts" };
                    if (battInfo['OtherIdentifyingInfo']) { batt["Other Info"] = battInfo['OtherIdentifyingInfo']; }
                    x += FullTable(batt, '');
                }
            }
            x += '<br>';

            QH('id_TableSysInfo', x);
            updateSystemStatus();
        }

        // ###BEGIN###{FileSaver}
        function SaveHardwareLog() {
            if (!xxdialogMode && HardwareInventory) SaveJsonFile('IntelAmtHardware', 'hardware', "Informations sur le matériel Intel AMT", HardwareInventory);
        }
        // ###END###{FileSaver}

// ###END###{HardwareInfo}

        //
        // POWER POLICY
        //

        var AmtSystemPowerSchemes = null;
        function PullPowerPolicy() { amtstack.Enum('AMT_SystemPowerScheme', powerPolicyResponse); }
        function powerPolicyResponse(stack, name, response, status) { AmtSystemPowerSchemes = response; updateSystemStatus(); }

        function showPowerPolicyDlg(currentguid) {
            if (xxdialogMode) return;
            var s = '';

            // Now find the name of the power schema in the AMT_SystemPowerScheme table
            for (var j = 0; j < AmtSystemPowerSchemes.length; j++) {
                var selected = ((AmtSystemPowerSchemes[j]['SchemeGUID'] == currentguid)?' checked':'');
                s += '<input type=radio name=powerpolicy value=\"' + AmtSystemPowerSchemes[j]['InstanceID'] + '\" ' + selected + '>' + AmtSystemPowerSchemes[j]['Description'] + '<br>';
            }

            setDialogMode(11, "Politique d'alimentation Intel&reg; AMT", 3, showPowerPolicyDlgOk, s);
        }

        function showPowerPolicyDlgOk() {
            var id = null, i = 0, e = document.getElementsByTagName('input');
            for (; i < e.length; i++) { if (e[i].name == 'powerpolicy' && e[i].checked) { id = e[i].value; } }
            amtstack.AMT_SystemPowerScheme_SetPowerScheme(showPowerPolicyDlgOkDone, id);
        }

        function showPowerPolicyDlgOkDone(stack, name, response, status) { if (status == 200) PullSystemStatus(); }

        //
        // USER INFORMATION PANEL
        //

        var xxAccountAdminName, xxAccountRealmInfo, xxAccountEnabledInfo = {}, xxAccountFetch, showHiddenAccounts = false;

        function PullUserInfo() {
            xxAccountFetch = 1;
            delete xxAccountAdminName;
            xxAccountRealmInfo = {};
            amtstack.AMT_AuthorizationService_GetAdminAclEntry(getAdminAclEntryResponse);
            amtstack.AMT_AuthorizationService_EnumerateUserAclEntries(1, enumerateUserAclEntriesResponse);
        }

        function getAdminAclEntryResponse(stack, name, response, status) {
            if (status != 200) return;
            xxAccountRealmInfo[-1] = { 'AccessPermission': 999, 'DigestUsername': response.Body['Username'], 'Realms':null };
            xxAccountAdminName = response.Body['Username'];
            updateAccounts();
        }

        function enumerateUserAclEntriesResponse(stack, name, response, status) {
            if (status != 200) return;
            //if (errcheck(status, stack)) return;
            methodcheck(response);
            QV('go11', true); // Show "User Accounts" on left panel
            xxAccountFetch = response.Body['Handles'].length;
            for (var i in response.Body['Handles']) {
                var h = response.Body['Handles'][i];
                amtstack.AMT_AuthorizationService_GetAclEnabledState(h, getAclEnabledStateResponse, h);
                amtstack.AMT_AuthorizationService_GetUserAclEntryEx(h, getUserAclEntryExResponse, h);
            }
            updateAccounts();
        }

        function getUserAclEntryExResponse(stack, name, response, status, tag) {
            xxAccountFetch--;
            //if (errcheck(status, stack)) return;
            //methodcheck(response);
            if (status == 200) { // Sometimes Intel AMT will just freak out on this call, if it's the case, just carry on.
                response.Body['Handle'] = tag;
                if (!response.Body['Realms']) response.Body['Realms'] = [];
                else if (!Array.isArray(response.Body['Realms'])) response.Body['Realms'] = [response.Body['Realms']]; // If "Realms" is not an array, it's because it's just one realm. Fix is so it's an array of one.
                xxAccountRealmInfo[tag] = response.Body;
                updateAccounts();
            }
        }

        function getAclEnabledStateResponse(stack, name, response, status, tag) {
            //if (errcheck(status, stack)) return;
            if (status == 200) { // Sometimes Intel AMT will just freak out on this call, if it's the case, just carry on.
                xxAccountEnabledInfo[tag] = response.Body;
                updateAccounts();
            }
        }

        function setAclEnabledStateResponse(stack, name, response, status, tag) {
            if (errcheck(status, stack)) return;
            methodcheck(response);
            amtstack.AMT_AuthorizationService_GetAclEnabledState(tag, getAclEnabledStateResponse, tag);
        }

        function updateAccounts() {
            if (xxAccountFetch > 0) return;
            var x = TableStart2();
            x += '<tr><td class=r1 style=padding-left:15px><br>' + "Gérez les comptes d'utilisateurs Intel&reg; AMT pour cet ordinateur." + '<br><br>';
            for (var i in xxAccountRealmInfo) {
                var r = xxAccountRealmInfo[i], name, hidden = false, state = 0;
                if (r['DigestUsername']) { name = r['DigestUsername']; hidden = (name[0] == '$' && name[1] == '$'); } else { name = GetSidString(atob(r['KerberosUserSid'])); }
                if (xxAccountEnabledInfo[i] && name != '$$OsAdmin') { state = (xxAccountEnabledInfo[i]['Enabled'] == true)?1:2; }
                if (showHiddenAccounts || !hidden) {
                    var rb = '';
                    if (r['AccessPermission'] != 999) {
                        if (state == 2) { rb += "Désactivé,"; }
                        var rc = 0;
                        for (i in r['Realms']) { if (amtstack.RealmNames[r["Royaumes"][i]] != '') { rc++; } } // Count only realms that have a name, removing reserved realms.
                        if (r['Realms'].indexOf(20) >= 0) rb += "Auditeur,";
                        if (r['Realms'].indexOf(3) >= 0) { rb += "Administrateur"; } else { if (rc == 1) { rb += "1 royaume"; } else { rb += rc + " royaumes"; } }
                    } else {
                        rb += "Administrateur";
                        r['Handle'] = -1;
                    }
                    x += '<div class=itemBar onclick=showUserDetails(' + r['Handle'] + ')><div style=float:right>';
                    if (state > 0 && xxAccountAdminName) x += ' ' + AddButton2((state == 1?'Disable':'Enable'), 'changeAccountStateButton(event,' + r['Handle'] + ',' + state + ')');
                    if (!hidden && xxAccountAdminName) x += ' ' + AddButton2("Éditer...", 'changeAccountButton(event,' + r['Handle'] + ')');
                    x += '</div><div style=padding-top:3px;width:330px;float:left;overflow-x:hidden title="' + name + '"><b>' + name + '</b></div><div style=padding-top:3px>' + rb + '</div></div>';
                }
            }
            var y = '<div style=float:right;margin-right:8px><a title="' + "Basculer les comptes cachés" + '" style=color:gray;cursor:pointer onclick=toggleAccountButton()>' + (showHiddenAccounts?'&#x25B2;':'&#x25BC;') + '</a></div><div>&nbsp;' + AddRefreshButton('xxAccountFetch=999;PullUserInfo()');
            if (xxAccountAdminName) y += AddButton("Nouveau compte", 'newAccountButton()');
            x += '<br><td class=r1>' + TableEnd(y + '</div>');
            QH('id_TableUserAccounts', x);
        }

        function toggleAccountButton() {
            showHiddenAccounts = !showHiddenAccounts;
            updateAccounts();
        }

        function removeUserAclEntryResponse(stack, name, response, status, tag) {
            if (methodcheck(response)) return;
            PullUserInfo();
        }

        function changeAccountStateButton(e, h, s) {
            haltEvent(e);
            if (xxdialogMode) return;
            amtstack.AMT_AuthorizationService_SetAclEnabledState(h, (s==1?false:true), setAclEnabledStateResponse, h);
        }

        function changeAccountButton(e, h) {
            haltEvent(e);
            if (xxdialogMode) return;
            updateRealms(xxAccountRealmInfo[h]['Realms']);
            d2username.value = xxAccountRealmInfo[h]['DigestUsername'] ? xxAccountRealmInfo[h]['DigestUsername'] : GetSidString(atob(xxAccountRealmInfo[h]['KerberosUserSid']));
            d2password1.value = d2password2.value = '';
            d2permission.value = xxAccountRealmInfo[h]['AccessPermission'];
            setDialogMode(2, "Modifier le compte", ((h==-1)?3:7), function (button) { changeAccountButtonEx(h, button); }); // If handle is -1, only display OK/Cancel buttons, if not, also display delete button.
            updateAccountDialog();
        }

        function newAccountButton() {
            if (xxdialogMode) return;
            updateRealms([]);
            d2username.value = d2password1.value = d2password2.value = '';
            d2permission.value = 2;
            setDialogMode(2, "Nouveau compte", 3, function () { changeAccountButtonEx(null, 1); });
            updateAccountDialog();
        }

        function changeAccountButtonEx(h, button) {
            if (button == 1) { // OK Button
                var realms = [], username = d2username.value, permission = d2permission.value, password = d2password1.value, sid = GetSidByteArray(Q('d2username').value), d = null;
                if (username.length == 0 || password != d2password2.value) { messagebox("Erreur de compte", "Paramètres invalides"); return; }
                if (sid == null) { d = window.btoa(rstr_md5(username + ":" + amtsysstate['AMT_GeneralSettings'].response['DigestRealm'] + ":" + password)); } else { username = null; sid = btoa(sid); }
                if (h != -1) { for (var y in amtstack.RealmNames) { if (((amtstack.RealmNames[y]) || (y == 3)) && Q('rx' + y).checked) { realms.push(y); } } }
                if (h == null) { amtstack.AMT_AuthorizationService_AddUserAclEntryEx(username, d, sid, permission, realms, userAclEntryExResponse); }
                else if (h == -1) { amtstack.AMT_AuthorizationService_SetAdminAclEntryEx(username, d, userAclEntryExResponse); }
                else { amtstack.AMT_AuthorizationService_UpdateUserAclEntryEx(h, username, d, sid, permission, realms, userAclEntryExResponse); }
            }
            if (button == 2) { // Delete Button
                amtstack.AMT_AuthorizationService_RemoveUserAclEntry(h, removeUserAclEntryResponse);
            }
        }

        function userAclEntryExResponse(stack, name, response, status, tag) { if (methodcheck(response)) return; PullUserInfo(); }
        function updateRealms(r) {
            QV('id_d2permissions', r != null);
            if (r != null) {
                var x = '<li><label><input type=checkbox onchange=updateAccountDialog() id=rx3' + ((r.indexOf(3) >= 0)?' checked':'') + '>' + "Administrateur" + '</label></li><hr />';
                for (var y in amtstack.RealmNames) { var c = ''; if (r.indexOf(parseInt(y)) >= 0) c = ' checked'; if (amtstack.RealmNames[y]) x += '<li><label><input type=checkbox onchange=updateAccountDialog() id=rx' + y + c + '>' + amtstack.RealmNames[y] + '</label></li>'; }
                QH('id_d2realms', x);
            }
        }

        function updateAccountDialog() {
            var ok = true;
            if (Q('id_d2permissions').style.display != 'none') { ok = false; for (var y in amtstack.RealmNames) { if (((amtstack.RealmNames[y]) || (y == 3)) && Q('rx' + y).checked) { ok = true; } } }
            if (ok) { ok = ((d2username.value.length > 0) && (passwordcheck(d2password1.value)) && (d2password1.value == d2password2.value)); }
            QE('idx_dlgOkButton', ok);
        }

        var xxUserPermissions = ["Local seulement" , "Réseau uniquement", "Tout (local et réseau)"];
        function showUserDetails(h) {
            if (xxdialogMode) return;
            var a = xxAccountRealmInfo[h], x = '<div style=text-align:left>';
            var i, n = a['DigestUsername'];
            if (!n) n = GetSidString(atob(a['KerberosUserSid']));
            x += addHtmlValue("Nom", n);
            if (xxAccountEnabledInfo[h]) { x += addHtmlValue("Etat", ((xxAccountEnabledInfo[h]['Enabled'] == true)?"Activée":"désactivé")); }
            if (n == xxAccountAdminName) {
                x += addHtmlValue("Autorisation", "Administrateur");
            } else {
                x += addHtmlValue("Autorisation", xxUserPermissions[a['AccessPermission']]);
                var y = '';
                if (a['Realms'].indexOf(3) >= 0) {
                    y = "Administrateur";
                    if (a['Realms'].indexOf(20) >= 0) y += ", Auditeur";
                } else {
                    for (i in xxAccountRealmInfo[h]['Realms']) {
                        if (amtstack.RealmNames[a['Realms'][i]] != '') { // Remove blank reserved realms
                            if (y.length > 0) y += ",";
                            y += amtstack.RealmNames[a['Realms'][i]];
                        }
                    }
                }
                if (y.length == 0) y = "Aucun";
                x += addHtmlValue("Royaumes", '') + '<b>' + y + '</b>';
            }
            x += '</div>';
            messagebox("Compte" + n, x);
        }

        //
        // WSMAN BROWSER PANEL
        //

        // ###BEGIN###{WsmanBrowser}
        function wsmanQuery() {
            QH('id_wsresults', '');
            var selections = getSelectedOptions(Q('id_QuerySelect')), selections2 = [];
            for (var x in selections) { if (QS('WSB-' + selections[x]).display == '') selections2.push(selections[x]); }
            if (selections2.length == 0) return;
            QE('id_p12querybutton', false);
            if (selections2 && selections2.length > 0) { amtstack.BatchEnum("Navigateur", selections2, browserResponse, null, true); } // This is the only BatchEnum where we want to continue and get an answer even if one of the calls fails.
        }

        function browserResponse(stack, name, responses, status) {
            QE('id_p12querybutton', true);
            var h = '';
            for (var r in responses) {
                var response = responses[r];
                h += '<h2>' + r + '</h2><div style=margin-left:20px>';
                if (response.status == 200) { if (response.responses.length == 0) { h += ('<br>' + "(Vide)"); } else { h += ObjectToString(response.responses).replace(/Intel\(r\)/g, 'Intel&reg'); } } else { h += '<br><div style=color:red>' + "Erreur #" + response.status + '</div>'; }
                h += '</div><br>';
            }
            QH('id_wsresults', h);
        }

        function wsmanFilter() {
            var filter = idx_browserFilter.value.toLowerCase();
            for (var w in AllWsman) { QV('WSB-' + AllWsman[w], filter == '' || AllWsman[w].toLowerCase().indexOf(filter) >= 0); }
        }
        // ###END###{WsmanBrowser}

        //
        // Remote Terminal
        //

        // ###BEGIN###{Terminal}
        function connectTerminal() {
            if (!terminal) return;
            if (terminal.State == 0) {
                // ###BEGIN###{ComputerSelector}
                terminal.digestRealmMatch = amtstack.wsman.comm.digestRealm;
                // ###END###{ComputerSelector}
                // ###BEGIN###{Mode-MeshCentral2}
                terminal.tlsv1only = amtstack.wsman.comm.tlsv1only;
                terminal.Start(currentMeshNode._id, 16994, '*', '*', 0);
                // ###END###{Mode-MeshCentral2}
                // ###BEGIN###{ComputerSelector}
                // ###BEGIN###{Mode-NodeWebkit}

                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) {
                    terminal.Start(currentcomputer._id, 0, 'x', 'x', 0, wsstack.comm, meshCentralServer);
                } else {
                    // ###END###{MeshServerConnect}
                    var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls'])
                    terminal.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], wsstack.comm.getPeerCertificateFingerprint(), wsstack.comm.xtlsoptions);
                    // ###BEGIN###{MeshServerConnect}
                }
                // ###END###{MeshServerConnect}

                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{!Mode-NodeWebkit}
                terminal.tlsv1only = amtstack.wsman.comm.tlsv1only;
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls'])
                terminal.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls']);
                // ###END###{!Mode-NodeWebkit}
                // ###END###{ComputerSelector}
                // ###BEGIN###{Mode-Firmware}
                terminal.Start();
                // ###END###{Mode-Firmware}
            } else {
                terminal.Stop();
            }
        }

        function onTerminalStateChange(terminal, state) {
            // console.log("onTerminalStateChange: " + state);
            idx_connectbutton2.value = (state == 0) ? "Relier" : "Déconnecter";
            Q('id_termstatus').textContent = StatusStrs[state];
            QE('id_tpastebutton', state == 3);
            // ###BEGIN###{!Mode-NodeWebkit}
            QE('TermWD', state == 3);
            // ###END###{!Mode-NodeWebkit}
            switch (state) {
                case 0:
                    terminal.m.TermResetScreen();
                    terminal.m.TermDraw();
                    if (xxdialogMode == 3) setDialogMode();
                    // ###BEGIN###{Mode-MeshCentral2}
                    QV('termRecordIcon', false);
                    // ###END###{Mode-MeshCentral2}
                    if (terminal.disconnectCode == 2) { // BUSY
                        messagebox("Remote Terminal", "The remote device is busy, a session may already be open.");
                    } else if (terminal.disconnectCode == 3) { // UNSUPPORTED
                        messagebox("Remote Terminal", "The device indicated that this type of connection of not supported.");
                    }
                    break;
                case 3:
                    // ###BEGIN###{Mode-MeshCentral2}
                    if (terminal.serverIsRecording == true) { QV('termRecordIcon', true); }
                    // ###END###{Mode-MeshCentral2}
                    break;
            }
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
        }

        function termPaste() { terminal.m.TermSendKeys(d3pastetextarea.value); return false; }
        function termSendKey(k) { terminal.m.TermSendKey(k); return false; }
        function termSendKeys() { var k = Q('termkeys').value; if (k < 1000) { termSendKey(k); } else { terminal.m.TermHandleKeyDown({ which: k - 889, repeat: false }); } }

        // ###BEGIN###{TerminalSize}
        function termToggleSize() {
            if (terminal.m.width == 80) {
                Q('id_tsizebutton').value = '100x30';
                terminal.m.Init(100, 30);
            } else {
                Q('id_tsizebutton').value = '80x25';
                terminal.m.Init(80, 25);
            }
        }
        // ###END###{TerminalSize}

        // ###BEGIN###{Terminal-Enumation-All}
        var terminalEmulations = ["Terminal UTF8", "ASCII étendu", "Intel ASCII"];
        function termToggleType() {
            terminal.m.terminalEmulation = (terminal.m.terminalEmulation + 1) % 3;
            Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
        }
        // ###END###{Terminal-Enumation-All}

        // ###BEGIN###{Terminal-FxEnumation-All}
        function termToggleFx() {
            Q('id_tfxkeysbutton').value = ["Intel (F10 = ESC + [OM)", "Alternatif (F10 = ESC + 0)", "VT100 + (F10 = ESC + [OY)"][terminal.m.fxEmulation = (terminal.m.fxEmulation + 1) % 3];
        }
        // ###END###{Terminal-FxEnumation-All}

        function termToggleCr() {
            if (terminal.m.lineFeed == '\r\n') {
                Q('id_tcrbutton').value = "LF";
                terminal.m.lineFeed = '\n';
            } else {
                Q('id_tcrbutton').value = "CR + LF";
                terminal.m.lineFeed = '\r\n';
            }
        }

        // ###BEGIN###{FileSaver}
        function terminalCaptureToggle(e) {
            if (xxdialogMode) return;
            // ###BEGIN###{TerminalReplay}
            if ((e != null) && (e.shiftKey == true)) { terminalReplay(); return; }
            if (terminalReplayTimer != null) { return; }
            // ###END###{TerminalReplay}
            if (terminal.m.capture == undefined) {
                terminal.m.capture = ''; // Start terminal capture
                // ###BEGIN###{!Mode-NodeWebkit}
                idx_terminalCaptureButton.value = "Arrêter la capture";
                // ###END###{!Mode-NodeWebkit}
            } else {
                if (terminal.m.capture.length > 0) {
                    var n = 'TerminalCapture', d = new Date();
                    if (amtsysstate) { n += '-' + amtsysstate['AMT_GeneralSettings'].response['HostName']; }
                    n += '-' + d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
                    // ###BEGIN###{!Mode-NodeWebkit}
                    saveAs(data2blob(terminal.m.capture), n + '.txt');
                    delete terminal.m.capture;
                    idx_terminalCaptureButton.value = "Commencer la capture";
                    // ###END###{!Mode-NodeWebkit}
                    // ###BEGIN###{Mode-NodeWebkit}
                    var chooser = document.createElement('input');
                    chooser.setAttribute('type', 'file');
                    chooser.setAttribute('nwsaveas', n + '.txt');
                    chooser.addEventListener('change', function() {
                        require('fs').writeFile(this.value, terminal.m.capture, function () { });
                        delete terminal.m.capture;
                    }, false);
                    chooser.click();
                    // ###END###{Mode-NodeWebkit}
                } else {
                    delete terminal.m.capture;
                    // ###BEGIN###{!Mode-NodeWebkit}
                    idx_terminalCaptureButton.value = "Commencer la capture";
                    // ###END###{!Mode-NodeWebkit}
                }
            }
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        // ###BEGIN###{TerminalReplay}
        function terminalReplay() {
            if (xxdialogMode) return;
            if (terminalReplayTimer != null) {
                clearInterval(terminalReplayTimer); terminalReplayBuffer = null; terminalReplayBufferPtr = 0; terminalReplayTimer = null;
                // ###BEGIN###{Mode-NodeWebkit}
                NW_SetupMainMenu(currentView);
                // ###END###{Mode-NodeWebkit}
            } else {
                setDialogMode(11, "Open Terminal Capture", 3, terminalReplayEx, '<input id=termCaptureFile type=file style=width:100% accept=.txt>');
            }
        }

        function terminalReplayEx() {
            var x = Q('termCaptureFile');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = terminalReplayEx2;
            reader.readAsBinaryString(x.files[0]);
        }

        var terminalReplayBuffer = null;
        var terminalReplayBufferPtr = 0;
        var terminalReplayTimer = null;
        function terminalReplayEx2(file) {
            terminal.m.TermResetScreen();
            if (terminalReplayTimer != null) { clearInterval(terminalReplayTimer); terminalReplayTimer = null; }
            terminalReplayBufferPtr = 0;
            terminalReplayBuffer = file.target.result;
            terminalReplayTimer = setInterval(terminalReplayEx3, 5);
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
        }

        function terminalReplayEx3() {
            var len = ((terminalReplayBufferPtr - 1) < terminalReplayBuffer.length) ? 2 : 1;
            var x = terminalReplayBuffer.substring(terminalReplayBufferPtr, terminalReplayBufferPtr + len);
            terminal.m.ProcessData(x);
            terminalReplayBufferPtr += len;
            if (terminalReplayBufferPtr >= terminalReplayBuffer.length) {
                clearInterval(terminalReplayTimer); terminalReplayBuffer = null; terminalReplayBufferPtr = 0; terminalReplayTimer = null;
                // ###BEGIN###{Mode-NodeWebkit}
                NW_SetupMainMenu(currentView);
                // ###END###{Mode-NodeWebkit}
            }
        }

        // ###END###{TerminalReplay}

        function terminal_FileSelectHandler(e) {
            haltEvent(e);
            if (terminal.State != 3 || e.dataTransfer == null || e.dataTransfer.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = terminal_onSetupBinRead;
            reader.readAsText(e.dataTransfer.files[0]);
        }

        function terminal_onSetupBinRead(file) {
            d3pastetextarea.value = file.target.result;
            setDialogMode(3, "Pâte", 3, termPaste)
        }

        // ###END###{Terminal}

        //
        // Remote Desktop
        //

        // ###BEGIN###{Desktop}

        // ###BEGIN###{Desktop-Multi}
        var desktopScreenInfo = null;
        var desktopPollTimer = null;
        // ###END###{Desktop-Multi}
        // ###BEGIN###{DesktopInband}
        var webRtcDesktop = null;
        function webRtcDesktopReset() {
            if (webRtcDesktop == null) return;
            if (webRtcDesktop.softdesktop != null) { webRtcDesktop.softdesktop.Stop(); webRtcDesktop.softdesktop = null; }
            if (webRtcDesktop.webchannel != null) { try { webRtcDesktop.webchannel.close(); } catch (e) { } webRtcDesktop.webchannel = null; }
            if (webRtcDesktop.webrtc != null) { try { webRtcDesktop.webrtc.close(); } catch (e) { } webRtcDesktop.webrtc = null; }
            webRtcDesktop = null;
            // Switch back to hardware KVM
            desktop.m.hold(false);
            updateDesktopState();
            // ###BEGIN###{DesktopInbandFiles}
            p24files = null;
            p24downloadFileCancel() // If any downloads are in process, cancel them.
            p24uploadFileCancel(); // If any uploads are in process, cancel them.
            QV('go24', false); // Files
            if (currentView == 24) { go(14); }
            // ###END###{DesktopInbandFiles}
        }

        /*
        function webRtcDesktopProcessData(data) {
            console.log('WebRTC data, len = ' + data.length);
        }
        */
        // ###END###{DesktopInband}

        function connectDesktopButton(e) { desktop.disconnectCode = 0; connectDesktop(e); }

        var connectDesktopConsent = false;
        function connectDesktop(skipConsent) {
            if (!desktop || xxdialogMode) return;
            connectDesktopConsent = false; // TODO, this is not a good idea when calls are pending.
            if (desktop.State == 0) {
                // Check if user consent is needed
                if ((skipConsent !== true) && (amtversion > 5) && ((amtsysstate == null) || (amtsysstate != null) && (amtsysstate['IPS_OptInService'] != null) && (amtsysstate['IPS_OptInService'].response != null) && (amtsysstate['IPS_OptInService'].response['OptInRequired'] != 0))) {
                    connectDesktopConsent = true; amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1); return; // User consent always required, ask for it before KVM.
                }
                // Encoding Flags: 1 = RLE, 2 = 16bit, 4 = Gray, 8 = ZLib, 16 = 4bit Color
                desktop.m.useRLE = ((desktopsettings.encflags & 1) != 0);
                desktop.m.bpp = (desktopsettings.encflags & 2) ? 2 : 1;
                if ((amtversion > 15) && (amtsysstate != null) && (amtsysstate['IPS_KVMRedirectionSettingData'] != null) && (amtsysstate['IPS_KVMRedirectionSettingData'].response)) {
                    desktop.m.lowcolor = amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported'] && ((desktopsettings.encflags & 16) != 0);
                    desktop.m.graymode = amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported'] && ((desktopsettings.encflags & 4) != 0);
                    desktop.m.useZLib = amtsysstate['IPS_KVMRedirectionSettingData'].response['ZlibControlSupported'] && ((desktopsettings.encflags & 8) != 0);
                    desktop.m.decimationMode = ((amtsysstate['IPS_KVMRedirectionSettingData'].response['InitialDecimationModeForLowRes'] > 0) ? desktopsettings.decimationMode : 0);
                } else {
                    desktop.m.lowcolor = false;
                    desktop.m.graymode = false;
                    desktop.m.useZLib = false;
                    desktop.m.decimationMode = 0;
                }
                desktop.m.showmouse = desktopsettings.showmouse;
                desktop.m.onScreenSizeChange = center;
                // ###BEGIN###{ComputerSelector}
                desktop.digestRealmMatch = amtstack.wsman.comm.digestRealm;
                // ###END###{ComputerSelector}
                // ###BEGIN###{DesktopInband}
                desktop.m.onKvmData = function(x) {
                    //console.log('onKvmData (' + x.length + '): ' + x);
                    var data = null;
                    try { data = JSON.parse(x); } catch (e) {}
                    if ((data != null) && (data.action != null)) {
                        if (data.action == 'restart') {
                            // Clear WebRTC channel
                            webRtcDesktopReset();
                            desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 }));
                        } else if ((data.action == 'present') && (webRtcDesktop == null)) {
                            // Setup WebRTC channel
                            webRtcDesktop = { platform: data.platform };
                            var configuration = null; //{ "iceServers": [ { 'urls': 'stun:stun.services.mozilla.com' }, { 'urls': 'stun:stun.l.google.com:19302' } ] };
                            if (typeof RTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new RTCPeerConnection(configuration); }
                            else if (typeof webkitRTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new webkitRTCPeerConnection(configuration); }

                            webRtcDesktop.webchannel = webRtcDesktop.webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
                            webRtcDesktop.webchannel.onopen = function () {
                                // Switch to software KVM
                                if (urlvars && urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Open'); }
                                desktop.m.hold(true);
                                webRtcDesktop.webRtcActive = true;
                                webRtcDesktop.softdesktop = CreateKvmDataChannel(webRtcDesktop.webchannel, CreateAgentRemoteDesktop('Desk', Q('id_mainarea')), desktop.m);
                                webRtcDesktop.softdesktop.m.setRotation(desktop.m.rotation);
                                if (desktopsettings.quality) { webRtcDesktop.softdesktop.m.CompressionLevel = desktopsettings.quality; } // Number from 1 to 100. 50 or less is best.
                                if (desktopsettings.scaling) { webRtcDesktop.softdesktop.m.ScalingLevel = desktopsettings.scaling; }
                                webRtcDesktop.softdesktop.Start();
                                updateDesktopState();

                                // Check if we can get remote file access
                                // ###BEGIN###{DesktopInbandFiles}
                                QV('go24', true); // Files
                                downloadFile = null;
                                p24files = webRtcDesktop.softdesktop;
                                p24targetpath = '';
                                webRtcDesktop.softdesktop.onControlMsg = onFilesControlData;
                                webRtcDesktop.softdesktop.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: '' })); // Ask for the root folder
                                // ###END###{DesktopInbandFiles}
                            }
                            webRtcDesktop.webchannel.onclose = function (event) { if (urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Closed'); } webRtcDesktopReset(); }
                            webRtcDesktop.webrtc.onicecandidate = function (e) {
                                if (e.candidate == null) {
                                    desktop.m.sendKvmData(JSON.stringify({ action: 'offer', ver: 1, sdp: webRtcDesktop.webrtcoffer.sdp }));
                                } else {
                                    webRtcDesktop.webrtcoffer.sdp += ('a=' + e.candidate.candidate + '\r\n'); // New candidate, add it to the SDP
                                }
                            }
                            webRtcDesktop.webrtc.oniceconnectionstatechange = function () {
                                if ((webRtcDesktop != null) && (webRtcDesktop.webrtc != null) && ((webRtcDesktop.webrtc.iceConnectionState == 'disconnected') || (webRtcDesktop.webrtc.iceConnectionState == 'failed'))) { /*console.log('WebRTC ICE Failed');*/ webRtcDesktopReset(); }
                            }
                            webRtcDesktop.webrtc.createOffer(function (offer) {
                                // Got the offer
                                webRtcDesktop.webrtcoffer = offer;
                                webRtcDesktop.webrtc.setLocalDescription(offer, function () { }, webRtcDesktopReset);
                            }, webRtcDesktopReset, { mandatory: { OfferToReceiveAudio: false, OfferToReceiveVideo: false } });
                        } else if ((data.action == 'answer') && (webRtcDesktop != null)) {
                            // Complete the WebRTC channel
                            webRtcDesktop.webrtc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: data.sdp }), function () { }, webRtcDesktopReset);
                        }
                    }
                };
                if ((amtversion > 15) || urlvars['kvmext']) { desktop.m.kvmExtChanged = updateDesktopState; } else { desktop.m.kvmExtChanged = null; }
                // ###END###{DesktopInband}
                desktop.m.frameRateDelay = ((desktopsettings.limitFrameRate == true)?200:0);
                desktop.m.noMouseRotate = desktopsettings.noMouseRotate;
                desktop.m.ReverseMouseWheel = desktopsettings.reverseMouseWheel;
                // ###BEGIN###{Mode-MeshCentral2}
                desktop.tlsv1only = amtstack.wsman.comm.tlsv1only;
                desktop.Start(currentMeshNode._id, 16994, '*', '*', 0);
                // ###END###{Mode-MeshCentral2}
                // ###BEGIN###{ComputerSelector}
                // ###BEGIN###{Mode-NodeWebkit}

                // ###BEGIN###{MeshServerConnect}
                if (meshCentralServer != null) {
                    desktop.Start(currentcomputer._id, 0, 'x', 'x', 0, wsstack.comm, meshCentralServer);
                } else {
                // ###END###{MeshServerConnect}
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                if ((amtsysstate) && (amtsysstate['IPS_ScreenConfigurationService'] != null) && ((amtsysstate['IPS_ScreenConfigurationService'].response['EnabledState'] & 1) != 0)) {
                    amtstack.IPS_ScreenConfigurationService_SetSessionState(Q('id_DeskSB').checked == true ? 1 : 0, 3, function (stack, name, responses, status) {
                        if (status != 200) { Q('id_DeskSB').checked = false; } // Screen blanking command is not supported, uncheck the screen blanking
                        desktop.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], wsstack.comm.getPeerCertificateFingerprint(), wsstack.comm.xtlsoptions);
                    });
                } else {
                    desktop.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], wsstack.comm.getPeerCertificateFingerprint(), wsstack.comm.xtlsoptions);
                }
                // ###BEGIN###{MeshServerConnect}
                }
                // ###END###{MeshServerConnect}


                // ###END###{Mode-NodeWebkit}
                // ###BEGIN###{!Mode-NodeWebkit}
                desktop.tlsv1only = amtstack.wsman.comm.tlsv1only;
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                if ((amtsysstate) && (amtsysstate['IPS_ScreenConfigurationService'] != null) && ((amtsysstate['IPS_ScreenConfigurationService'].response['EnabledState'] & 1) != 0)) {
                    amtstack.IPS_ScreenConfigurationService_SetSessionState(Q('id_DeskSB').checked == true ? 1 : 0, 3, function (stack, name, responses, status) {
                        if (status != 200) { Q('id_DeskSB').checked = false; } // Screen blanking command is not supported, uncheck the screen blanking
                        desktop.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls']);
                    });
                } else {
                    desktop.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls']);
                }
                // ###END###{!Mode-NodeWebkit}
                // ###END###{ComputerSelector}
                // ###BEGIN###{Mode-Firmware}
                desktop.Start();
                // ###END###{Mode-Firmware}
                // ###BEGIN###{Desktop-Multi}
                PullDesktopDisplayInfo();

                if (!urlvars['norefresh']) { desktopPollTimer = setInterval(PullDesktopDisplayInfo, 5000); }

                // ###END###{Desktop-Multi}
            } else {
                desktop.Stop();
                // ###BEGIN###{Desktop-Multi}
                clearInterval(desktopPollTimer);
                desktopPollTimer = null;
                PullDesktopDisplayInfo();
                // ###END###{Desktop-Multi}
                // ###BEGIN###{DesktopInband}
                webRtcDesktopReset();
                // ###END###{DesktopInband}
            }
        }

        // ###BEGIN###{Desktop-Multi}
        function PullDesktopDisplayInfo() {
            if ((amtversion > 7) && (desktop.State > 0)) { amtstack.BatchEnum('', ['*IPS_ScreenSettingData', '*IPS_KVMRedirectionSettingData'], ProcessDesktopDisplayInfo); } else { desktopScreenInfo = null; Q('id_DeskScreenSelector').innerHTML = '' }
        }

        // Update the currently active displays
        function ProcessDesktopDisplayInfo(stack, name, responses, status) {
            if (status != 200) { desktopScreenInfo = null; return; }
            desktopScreenInfo = responses['IPS_ScreenSettingData'].responses.Body;
            desktopScreenInfo.KVMRSD = responses['IPS_KVMRedirectionSettingData'].responses.Body;
            UpdateDesktopDisplayInfo();
        }

        // Update screen icons
        function UpdateDesktopDisplayInfo() {
            var buttons = '', activeScreens = 0;
            for (var i = 0; i < 3; i++) { if (desktopScreenInfo['IsActive'][i] == true) { activeScreens++; buttons += '<input type="button" ' + ((i == desktopScreenInfo.KVMRSD['DefaultScreen'])?'style="background-color:DodgerBlue"':'') + ' value="' + (i + 1) + '" title="Switch to screen ' + (i + 1) + '" onkeypress="return false" onkeydown="return false" onclick="desktopSwitchScreen(' + i + ')">&nbsp;'; } }
            if (activeScreens > 1) { Q('id_DeskScreenSelector').innerHTML = buttons + '&nbsp;'; } else { Q('id_DeskScreenSelector').innerHTML = ''; }
        }

        // Request switch to a different desktop
        function desktopSwitchScreen(x) {
            var k = Clone(desktopScreenInfo.KVMRSD); k['DefaultScreen'] = x; amtstack.Put('IPS_KVMRedirectionSettingData', k, desktopSwitchScreenEx);
        }

        // Response to request for a different desktop
        function desktopSwitchScreenEx(stack, name, responses, status) {
            if (status == 200) { desktopScreenInfo.KVMRSD = responses.Body; UpdateDesktopDisplayInfo(); }
        }
        // ###END###{Desktop-Multi}

        function onDesktopStateChange(desktop, state) {
            var reconnect = false;
            //console.log("onDesktopStateChange: " + state);
            idx_connectbutton1.value = (state == 0) ? "Relier" : "Déconnecter";
            var input = ((state == 3) && !urlvars['kvmviewonly']);
            QE('id_DeskCAD', input);
            QE('deskkeys', input);
            QE('DeskWD', input);
            // ###BEGIN###{DesktopType}
            QE('id_DeskType', input);
            // ###END###{DesktopType}
            // ###BEGIN###{DesktopClipboard}
            QE('id_DeskKvmClipButton', state == 3);
            // ###END###{DesktopClipboard}
            switch (state) {
                case 0:
                    // ###BEGIN###{DesktopRecorder}
                    if (desktop.m.recordedData != null) { deskRecordSession(); }
                    // ###END###{DesktopRecorder}
                    // desktop.m.ResetScreen();
                    // ###BEGIN###{DesktopInband}
                    webRtcDesktopReset();
                    // ###END###{DesktopInband}
                    // ###BEGIN###{Mode-MeshCentral2}
                    QV('deskRecordIcon', false);
                    // ###END###{Mode-MeshCentral2}
                    if (desktop.disconnectCode == 2) { // BUSY
                        messagebox("Bureau à distance", "The remote device is busy, a session may already be open.");
                    } else if (desktop.disconnectCode == 3) { // UNSUPPORTED
                        messagebox("Bureau à distance", "The device indicated that this type of connection of not supported.");
                    } else if (desktop.disconnectCode == 50000) { // KVM-Disconnect
                        messagebox("Bureau à distance", "KVM disconnection, this may indicate that Intel AMT is unable to capture the display (Try RLE8 encoding), or unsupported GPU.");
                    } else if (desktop.disconnectCode == 50001) { // Intel AMT disconnect, try to connect again if connection was more than 5 seconds long.
                        reconnect = (desktop.connectTime != null) && ((desktop.connectTime + 5000) < Date.now());
                        //console.log(desktop.disconnectCode, reconnect);
                    } else if (desktop.disconnectCode == 50002) { // KVM-BufferOverflow
                        messagebox("Bureau à distance", "KVM disconnection that may be due to the display size and resolution being too large for the Intel AMT KVM buffer. Try RLE8 encoding or reducing the display resolution.");
                    }
                    break;
                case 3:
                    // ###BEGIN###{DesktopInband}
                    if (amtversion >= 12) { desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 })); } // If this is Intel AMT 12 or higher, send the soft-KVM presence indicator.
                    // ###END###{DesktopInband}
                    // ###BEGIN###{Mode-MeshCentral2}
                    if (desktop.serverIsRecording == true) { QV('deskRecordIcon', true); }
                    // ###END###{Mode-MeshCentral2}
                    break;
            }
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(currentView);
            // ###END###{Mode-NodeWebkit}
            center();
            updateDesktopState();
            if (reconnect) { setTimeout(connectDesktop, 200); }
        }

        // Update remote desktop status
        function updateDesktopState() {
            // ###BEGIN###{DesktopInband}
            var x = '';
            if (desktop.State == 3) {
                if ((webRtcDesktop) && (webRtcDesktop.webRtcActive == true)) {
                    x = ", Soft-KVM";
                } else {
                    if (desktop.m && desktop.m.kvmExt) {
                        if (desktop.m.kvmExt.decimationState == 1) { x += ", Downscaled" }
                        if (desktop.m.kvmExt.compression == 1) { x += ", Compressed" }
                    }
                }
            }
            Q('id_deskstatus').textContent = StatusStrs[desktop.State] + x;
            // ###END###{DesktopInband}
            // ###BEGIN###{!DesktopInband}
            Q('id_deskstatus').textContent = StatusStrs[desktop.State];
            // ###END###{!DesktopInband}
        }

        function showDesktopSettings() {
            if (xxdialogMode) return;
            applyDesktopSettings();
            setDialogMode(7, "Paramètres du bureau à distance", 3, showDesktopSettingsChanged);
        }

        function showDesktopSettingsChanged() {
            desktopsettings.encflags = parseInt(idx_d7desktopmode.value);
            // ###BEGIN###{DesktopFocus}
            desktopsettings.showfocus = d7showfocus.checked;
            if ((amtversion > 15) && (amtsysstate['IPS_KVMRedirectionSettingData'].response['InitialDecimationModeForLowRes'] > 0)) { desktopsettings.decimationMode = parseInt(d7decimation.value); }
            // ###END###{DesktopFocus}
            desktopsettings.showmouse = d7showcursor.checked;
            desktopsettings.showcad = d7showcad.checked;
            desktopsettings.limitFrameRate = d7limitFrameRate.checked;
            desktopsettings.noMouseRotate = d7noMouseRotate.checked;
            desktopsettings.reverseMouseWheel = d7kvmrmw.checked;
            // ###BEGIN###{DesktopInband}
            desktopsettings.quality = d7bitmapquality.value;
            desktopsettings.scaling = d7bitmapscaling.value;
            // ###END###{DesktopInband}
            try { localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings)); } catch (ex) { }
            applyDesktopSettings();
            // ###BEGIN###{DesktopFocus}
            if (desktopsettings.showfocus == false) { desktop.m.focusmode = 0; idx_deskFocusBtn.value = "Tout se concentrer"; }
            // ###END###{DesktopFocus}
            desktop.m.frameRateDelay = (desktopsettings.limitFrameRate == true)?200:0;
            if (desktop.State != 0) { desktop.disconnectCode = 0; desktop.Stop(); setTimeout(connectDesktop, 800); }
        }

        function applyDesktopSettings() {
            // ###BEGIN###{DesktopFocus}
            d7showfocus.checked = desktopsettings.showfocus;
            // ###END###{DesktopFocus}
            d7decimation.value = desktopsettings.decimationMode;
            d7showcursor.checked = desktopsettings.showmouse;
            d7showcad.checked = desktopsettings.showcad;
            d7limitFrameRate.checked = desktopsettings.limitFrameRate;
            d7noMouseRotate.checked = desktopsettings.noMouseRotate;
            d7kvmrmw.checked = desktopsettings.reverseMouseWheel;
            // ###BEGIN###{DesktopInband}
            if (desktopsettings.quality) { d7bitmapquality.value = desktopsettings.quality; }
            if (desktopsettings.scaling) { d7bitmapscaling.value = desktopsettings.scaling; }
            QV('d7softkvmsettings', amtversion >= 12);
            // ###END###{DesktopInband}
            var encflags = desktopsettings.encflags; // Flags: 1 = RLE, 2 = 16bit, 4 = Gray, 8 = ZLib, 16 = 4bit Color

            var x = '';
            if ((amtversion > 15) && (amtsysstate != null) && (amtsysstate['IPS_KVMRedirectionSettingData'] != null) && (amtsysstate['IPS_KVMRedirectionSettingData'].response)) {
                if (!amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported']) { encflags = encflags & 11; } // Remove grayscale and lowcolor
                if (!amtsysstate['IPS_KVMRedirectionSettingData'].response['ZlibControlSupported']) { encflags = encflags & 23; } // Remove zlib
                if (amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported']) {
                    x += '<option id="d7exm1" value=21>' + "RLE4G, 16 Grays" + '</option>';
                    x += '<option id="d7exm2" value=5>' + "RLE8G, 256 Grays" + '</option>';
                }
                x += '<option value=1>' + "RLE8, 256 Colors" + '</option>';
                x += '<option value=3>' + "RLE16, 64k Colors" + '</option>';
                if (amtsysstate['IPS_KVMRedirectionSettingData'].response['ZlibControlSupported']) {
                    if (amtsysstate['IPS_KVMRedirectionSettingData'].response['GrayscalePixelFormatSupported']) {
                        x += '<option id="d7exm3" value=29>' + "ZRLE4G, Compressed Gray" + '</option>';
                        x += '<option id="d7exm4" value=13>' + "ZRLE8G, Compressed Gray" + '</option>';
                    }
                    x += '<option id="d7exm5" value=9>' + "ZRLE8, Compressed Color" + '</option>';
                    x += '<option id="d7exm6" value=11>' + "ZRLE16, Compressed Color" + '</option>';
                }
                QV('d7decimationspan', amtsysstate['IPS_KVMRedirectionSettingData'].response['InitialDecimationModeForLowRes'] > 0);
            } else {
                encflags = encflags & 3; // Remove gray & zlib flags (4 and 8), keep 1 & 2
                x += '<option value=1>' + "RLE8, 256 Colors" + '</option>';
                x += '<option value=3>' + "RLE16, 64k Colors" + '</option>';
                QV('d7decimationspan', false);
            }
            x += '<option value=0>' + "RAW8, 256 Colors" + '</option>';
            x += '<option value=2>' + "RAW16, 16k Colors" + '</option>';
            QH('idx_d7desktopmode', x);
            idx_d7desktopmode.value = encflags;
            // ###BEGIN###{DesktopFocus}
            QV('idx_deskFocusBtn', desktopsettings.showfocus);
            // ###END###{DesktopFocus}
            QV('id_DeskCAD', desktopsettings.showcad);
        }

        var fullscreen = false;
        var fullscreenonly = false;
        function deskToggleFull(kvmonly) {
            if (xxdialogMode) return;
            if (fullscreenonly == true) {
                // We are in full screen only mode
                console.log('deskToggleFull1', fullscreenonly, urlvars['kvmonly']);
                fullscreenonly = false;
                if (urlvars['kvmonly'] == 1) {
                    //console.log('deskToggleFull2');
                    // It was initiated by a command line switch, exit now.
                    // ###BEGIN###{Mode-NodeWebkit}
                    require('nw.gui').Window.get().close();
                    // ###END###{Mode-NodeWebkit}
                } else {
                    // It was initiated by a menu selection, disconnect now.
                    disconnect();
                }
                return;
            }
            fullscreenonly = kvmonly;
            fullscreen = !fullscreen;
            // ###BEGIN###{!Look-MeshCentral}
            QV('id_topheader', !fullscreen);
            // ###END###{!Look-MeshCentral}
            QV('id_leftbar', !fullscreen);
            QV('id_rdheader', !fullscreen);
            QV('idx_deskFullBtn', !fullscreen);
            QV('idx_deskFullBtn2', fullscreen);
            if (fullscreen) {
                // ###BEGIN###{!Look-MeshCentral}
                QS('id_mainarea').top = 0;
                // ###END###{!Look-MeshCentral}
                QS('id_mainarea').left = 0;
                QS('id_mainarea_pad').padding = 0;
            } else {
                // ###BEGIN###{!Look-MeshCentral}
                // ###BEGIN###{!Look-ISDU}
                QS('id_mainarea').top = '69px';
                // ###END###{!Look-ISDU}
                // ###BEGIN###{Look-ISDU}
                QS('id_mainarea').top = '94px';
                // ###END###{Look-ISDU}
                // ###END###{!Look-MeshCentral}
                QS('id_mainarea').left = '156px';
                QS('id_mainarea_pad').padding = '8px';
            }
            center();
        }

        // ###BEGIN###{DesktopFocus}
        function deskToggleFocus() {
            desktop.m.focusmode = (desktop.m.focusmode + 64) % 192;
            Q('idx_deskFocusBtn').value = ["Tout se concentrer", "Petit focus", "Large Focus"][desktop.m.focusmode / 64];
        }
        // ###END###{DesktopFocus}

        // ###BEGIN###{DesktopType}
        // Remote desktop typing
        function deskShowTypeDialog() {
            if (xxdialogMode || desktop.State != 3) return;
            Q('id_DeskType').blur();
            var x = '<div>' + "Saisissez le texte et cliquez sur OK pour le taper à distance à l'aide d'un clavier anglais américain. Assurez-vous de placer le curseur distant à la bonne position avant de continuer." + '<div>';
            x += '<textarea id=d2typeText style="margin-top:5px;width:100%;height:184px;resize:none" maxlength=2000></textarea>';
            setDialogMode(11, "Entrée clavier à distance", 3, showDeskTypeEx, x);
            Q('d2typeText').focus();
        }

        var AmtDeskTypeTimer = null;
        var AmtDeskTypeContent = null;
        var DeskTypeTranslate = { 39: 222, 42: 106, 43: 107, 44: 188, 45: 189, 46: 190, 47: 191, 59: 186, 61: 187, 91: 219, 92: 220, 93: 221, 96: 192, 191: 111 };
        var DeskTypeShiftTranslate = { 33: 49, 34: 222, 35: 51, 36: 52, 37: 53, 38: 55, 40: 57, 41: 48, 58: 186, 60: 188, 62: 190, 63: 191, 64: 50, 94: 54, 95: 189, 106: 56, 107: 187, 123: 219, 124: 220, 125: 221, 126: 192 };
        function showDeskTypeEx() {
            var txt = Q('d2typeText').value, ltxt = Q('d2typeText').value.toUpperCase(), x = [], shift = false;
            //if (desktop.contype == 2) {
                // Intel AMT
                for (var i in txt) { var a = txt.charCodeAt(i); x.push([a, 1], [a, 0]); }
                AmtDeskTypeContent = x;
                AmtDeskTypeTimer = setInterval(function () {
                    var key = AmtDeskTypeContent.shift();
                    if (desktop) { desktop.m.sendkey(key[0], key[1]); }
                    if ((desktop == null) || (AmtDeskTypeContent.length == 0)) { clearInterval(AmtDeskTypeTimer); AmtDeskTypeContent = null; }
                }, 10);
             /*
            } else {
                // MeshAgent
                for (var i in txt) {
                    var a = txt.charCodeAt(i), b = ltxt.charCodeAt(i);
                    if (((a >= 65) && (a <= 90)) || ((a >= 97) && (a <= 122))) {
                        if ((a == b) && (shift == false)) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
                        if ((a != b) && (shift == true)) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // LShift up
                    } else if ((a >= 48) && (a <= 57)) {
                        if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
                    } else if (DeskTypeTranslate[a]) {
                        if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
                        b = DeskTypeTranslate[a];
                    } else if (DeskTypeShiftTranslate[a]) {
                        if (shift == false) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
                        b = DeskTypeShiftTranslate[a];
                    }
                    x.push([desktop.m.KeyAction.DOWN, b], [desktop.m.KeyAction.UP, b]);
                }
                if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
                desktop.m.SendKeyMsgKC(x);
            }
            */
        }
        // ###END###{DesktopType}

        // Send CTRL-ALT-DEL
        function sendCAD() { if (!Q('id_DeskVO').checked) { desktop.m.sendcad(); } }

        // Special keys
        var deskkeysset = {
            0: [[0xffe7, 1], [0xffe7, 0]], // Win
            1: [[0xffe7, 1], [0xff54, 1], [0xff54, 0], [0xffe7, 0]], // Win+Down
            2: [[0xffe7, 1], [0xff52, 1], [0xff52, 0], [0xffe7, 0]], // Win+Up
            3: [[0xffe7, 1], [0x6c, 1], [0x6c, 0], [0xffe7, 0]], // Win+L
            4: [[0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0]], // Win+M
            5: [[0xffe1, 1], [0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0], [0xffe1, 0]], // Shift+Win+M
            6: [[0xffbe, 1], [0xffbe, 0]], // F1
            7: [[0xffbf, 1], [0xffbf, 0]], // F2
            8: [[0xffc0, 1], [0xffc0, 0]], // F3
            9: [[0xffc1, 1], [0xffc1, 0]], // F4
            10: [[0xffc2, 1], [0xffc2, 0]], // F5
            11: [[0xffc3, 1], [0xffc3, 0]], // F6
            12: [[0xffc4, 1], [0xffc4, 0]], // F7
            13: [[0xffc5, 1], [0xffc5, 0]], // F8
            14: [[0xffc6, 1], [0xffc6, 0]], // F9
            15: [[0xffc7, 1], [0xffc7, 0]], // F10
            16: [[0xffc8, 1], [0xffc8, 0]], // F11
            17: [[0xffc9, 1], [0xffc9, 0]], // F12
            //18: [[0xffe1, 1], [0xffe9, 1], [65, 1], [65, 0], [0xffe9, 0], [0xffe1, 0]]   // Left-Shift + Left-Alt + Print Screen
            19: [[0xffe9, 1], [0xff09, 1], [0xff09, 0], [0xffe9, 0]],  // Alt-Tab
            20: [[0xffe7, 1], [0x72, 1], [0x72, 0], [0xffe7, 0]], // WIN+R
            21: [[0xffe9, 1], [0xffc1, 1], [0xffc1, 0], [0xffe9, 0]], // Alt-F4
            22: [[0xffe3, 1], [0x77, 1], [0x77, 0], [0xffe3, 0]], // Ctrl-W
            23: [[0xffe7, 1], [0xff51, 1], [0xff51, 0], [0xffe7, 0]], // WIN+Left
            24: [[0xffe7, 1], [0xff53, 1], [0xff53, 0], [0xffe7, 0]], // Win+Right
            25: [[0xff0d, 1], [0xff0d, 0]] // Enter
        }

        // Send special keys to the remote side.
        function deskSendKeys() {
            if (Q('id_DeskVO').checked) return;
            var ks = Q('deskkeys').value;
            if (ks != null && deskkeysset[ks] != null && desktop.State != 0) {
                for (var i = 0; i < deskkeysset[ks].length; i++) {
                    desktop.m.sendkey(deskkeysset[ks][i][0], deskkeysset[ks][i][1]);
                }
            }
        }

        // ###BEGIN###{DesktopClipboard}
        // Toggle desktop session recording
        function deskClipboard() {
            if (xxdialogMode || (desktop == null) || (desktop.State != 3)) return;
            var x = '';
            x += "Saisissez le texte à envoyer au presse-papiers Intel&reg; AMT." + '<br />';
            x += '<select id=kvmClipEncoding style=width:100%;margin-top:8px><option value=0>' + "Text Encoding" + '<option value=1>' + "Hex Encoding" + '</select>';
            x += '<textarea id=kvmClipText style=width:100%;height:120px;resize:none;margin-top:8px />';
            setDialogMode(11, "Presse-papiers", 3, deskClipboardEx, x);
            focusTextBox('kvmClipText');
            if (xxKvmClipEnc != null) { Q('kvmClipEncoding').value = xxKvmClipEnc; }
            if (xxKvmClipVal != null) { Q('kvmClipText').value = xxKvmClipVal; }
        }

        function deskClipboardEx() {
            xxKvmClipEnc = Q('kvmClipEncoding').value;
            xxKvmClipVal = Q('kvmClipText').value;
            if (Q('kvmClipEncoding').value == 0) {
                desktop.m.sendClipboardData(Q('kvmClipText').value.split('\\0').join('\0')); // Text encoded input
            } else {
                desktop.m.sendClipboardData(hex2rstr(Q('kvmClipText').value)); // Hex encoded input
            }
        }
        // ###END###{DesktopClipboard}

        // ###BEGIN###{FileSaver}
        // ###BEGIN###{DesktopRecorder}
        // Toggle desktop session recording
        function deskRecordSession() {
            if ((desktop == null) || (urlvars && urlvars['norecord'])) return;
            if (desktop.m.recordedData == null) {
                // Start recording
                if ((desktop.State === 3) && (desktop.m.StartRecording())) { Q('DeskRecordButton').classList.remove('videoIcon'); Q('DeskRecordButton').classList.add('videoIconRed'); }
            } else {
                // Stop recording
                Q('DeskRecordButton').classList.remove('videoIconRed');
                Q('DeskRecordButton').classList.add('videoIcon');
                var d = new Date(), n = 'AmtDesktopSesion-' + currentcomputer['name'] + '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
                saveAs(data2blob(desktop.m.StopRecording().join('')), n + '.mcrec');
            }
        }
        // ###END###{DesktopRecorder}
        // ###END###{FileSaver}

        // ###BEGIN###{FileSaver}
        // Save the desktop image to file
        function deskSaveImage() {
            if (xxdialogMode || (desktop.State != 3) || (urlvars && urlvars['norecord'])) return;
            var n = 'Desktop', d = new Date();
            if (amtsysstate) { n += '-' + amtsysstate['AMT_GeneralSettings'].response['HostName']; }
            n += '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
            // ###BEGIN###{!Mode-NodeWebkit}
            Q('Desk')['toBlob']( function (blob) { saveAs(blob, n + '.jpg'); } );
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var b64image = document.getElementById('Desk').toDataURL('image/png').split(',')[1];
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file');
            chooser.setAttribute('nwsaveas', n + '.png');
            chooser.addEventListener('change', function () { console.log('cc'); require('fs').writeFile(this.value, b64image, 'base64', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        // Send special keys
        //function sendSpecialKey() { var k = Q('specialkeylist').value; desktop.m.sendkey(k, 1); desktop.m.sendkey(k, 0); }

        // ###BEGIN###{!DesktopInband}
        function dmousedown(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) desktop.m.mousedown(e); }
        function dmouseup(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) desktop.m.mouseup(e); }
        function dmousemove(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) desktop.m.mousemove(e); }
        function dmousewheel(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) desktop.m.mousewheel(e); }
        // ###END###{!DesktopInband}
        // ###BEGIN###{DesktopInband}
        function dmousedown(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedown(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedown(e); } } }
        function dmouseup(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mouseup(e); desktop.m.sendKeepAlive(); } else { desktop.m.mouseup(e); } } }
        function dmousemove(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousemove(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousemove(e); } } }
        function dmousewheel(e) { if (!xxdialogMode && (!Q('id_DeskVO').checked)) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousewheel(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousewheel(e); } } }
        // ###END###{DesktopInband}

        function drotate(x) {
            if (xxdialogMode) return;
            var r = desktop.m.rotation + x;
            desktop.m.setRotation(r);
            // ###BEGIN###{DesktopInband}
            if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null) && (webRtcDesktop.softdesktop.m != null)) {
                webRtcDesktop.softdesktop.m.setRotation(r); }
            // ###END###{DesktopInband}
            center();
        }

        // ###BEGIN###{DesktopInbandFiles}
        
        // 
        // Remote Files
        //

        var p24files = null;
        var p24filetree = null;
        var p24targetpath = null;
        var p24filetreelocation = [];

        function onFilesControlData(data) {
            if ((data.length > 0) && (data.charCodeAt(0) != 123)) { p24gotDownloadBinaryData(data); return; }
            data = JSON.parse(data);
            if (data.action == 'download') { p24gotDownloadCommand(data); return; }
            if (data.action == 'upload') { p24gotUploadData(data); return; }
            if (data.action == 'pong') { return; }
            data.path = data.path.replace(/\//g, '\\');
            if ((p24filetree != null) && (data.path == p24filetree.path)) {
                // This is an update to the same folder
                var checkedNames = p24getCheckedNames();
                p24filetree = data;
                p24updateFiles(checkedNames);
            } else {
                // Make both paths use the same seperator not start with /
                var x1 = data.path.split('/').join('\\');
                var x2 = p24targetpath.split('/').join('\\');
                while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
                while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
                if ((x1 == x2) || ((data.path == '\\') && (p24targetpath == ''))) {
                    // This is a different folder
                    p24filetree = data;
                    p24updateFiles();
                }
            }
        }

        function p24getCheckedNames() {
            // Save all existing checked boxes
            var checkedNames = [], checkboxes = document.getElementsByName('fd');
            for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkedNames.push(p24filetree.dir[checkboxes[i].value].n) }; }
            return checkedNames;
        }

        //var p24oldlinkpath = null;
        function p24updateFiles(checkedNames) {
            var html1 = '', html2 = '', displayPath = '<a style=cursor:pointer onclick=p24folderup(0)>' + "Racine" + '</a>', fullPath = 'Root';

            // Work on parsing the file path
            var x = p24filetree.path.split('\\');
            p24filetreelocation = [];
            for (var i in x) { if (x[i] != '') { p24filetreelocation.push(x[i]); } } // Remove empty spaces
            for (var i in p24filetreelocation) { displayPath += ' / <a style=cursor:pointer onclick=p24folderup(' + (parseInt(i) + 1) + ')>' + p24filetreelocation[i] + '</a>' } // Setup the path we display
            var newlinkpath = p24filetreelocation.join('/');

            // Sort the files
            var filetreexx = p24sort_files(p24filetree.dir);

            // Display all files and folders at this location
            for (var i in filetreexx) {
                // Figure out the name and shortname
                var f = filetreexx[i], name = f.n, shortname;
                shortname = name;
                if (name.length > 70) { shortname = '<span title="' + EscapeHtml(name) + '">' + EscapeHtml(name.substring(0, 70)) + "..." + '</span>'; } else { shortname = EscapeHtml(name); }
                name = EscapeHtml(name);

                // Figure out the date
                var fdatestr = '';
                if (f.d != null) { var fdate = new Date(f.d), fdatestr = (fdate.getMonth() + 1) + '/' + (fdate.getDate()) + '/' + fdate.getFullYear() + ' ' + fdate.toLocaleTimeString() + '&nbsp;'; }

                // Figure out the size
                var fsize = '';
                if (f.s != null) { fsize = getFileSizeStr(f.s); }

                var h = '';
                if (f.t < 3) {
                    var right = '', title = '';
                    h = '<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p24setActions() value="' + f.nx + '">&nbsp;<span style=float:right title=\"' + title + '\">' + right + '</span><span><div class=fileIcon' + f.t + '></div><a style=cursor:pointer onclick=p24folderset(\"' + encodeURIComponent(f.nx) + '\")>' + shortname + '</a></span></div>';
                } else {
                    var link = shortname;
                    if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\'p24downloadfile("' + encodeURIComponent(newlinkpath + '/' + name) + '","' + encodeURIComponent(name) + '",' + f.s + ')\'>' + shortname + '</a>'; }
                    h = '<div class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p24setActions() value="' + f.nx + '">&nbsp;<span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
                }

                if (f.t < 3) { html1 += h; } else { html2 += h; }
            }

            // Display the files and path
            QH('p24files', html1 + html2);
            QH('p24currentpath', displayPath);
            QE('p24FolderUp', p24filetreelocation.length != 0);

            // Re-check all boxes if needed using names
            if (checkedNames != null) { var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkedNames.indexOf(p24filetree.dir[checkboxes[i].value].n) >= 0) { checkboxes[i].checked = true; } } }

            // Update the actions buttons
            p24setActions();
        }

        function p24folderset(x) {
            p24targetpath = joinPaths(p24filetree.path, p24filetree.dir[x].n).split('\\').join('/');
            p24files.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: p24targetpath }));
        }

        function p24folderup(x) {
            if (x == null) { p24filetreelocation.pop(); } else { while (p24filetreelocation.length > x) { p24filetreelocation.pop(); } }
            p24targetpath = p24filetreelocation.join('/');
            p24files.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: p24targetpath }));
        }

        var p24sortorder;
        function p24sort_filename(a, b) { if (a.ln > b.ln) return (1 * p24sortorder); if (a.ln < b.ln) return (-1 * p24sortorder); return 0; }
        function p24sort_timestamp(a, b) { if (a.d > b.d) return (1 * p24sortorder); if (a.d < b.d) return (-1 * p24sortorder); return 0; }
        function p24sort_bysize(a, b) { if (a.s == b.s) return p24sort_filename(a, b); return (((a.s - b.s)) * p24sortorder); }

        function p24sort_files(files) {
            var r = [], sortselection = Q('p24sortdropdown').value;
            for (var i in files) { files[i].nx = i; if (files[i].s == null) { files[i].s = 0; } if (files[i].n == null) { files[i].n = i; } files[i].ln = files[i].n.toLowerCase(); r.push(files[i]); }
            p24sortorder = 1;
            if (sortselection > 3) { p24sortorder = -1; sortselection -= 3; }
            if (sortselection == 1) { r.sort(p24sort_filename); }
            else if (sortselection == 2) { r.sort(p24sort_bysize); }
            else if (sortselection == 3) { r.sort(p24sort_timestamp); }
            return r;
        }

        function p24setActions() {
            if (p24filetree == null) {
                QE('p24DeleteFileButton', false);
                QE('p24NewFolderButton', false);
                QE('p24UploadButton', false);
                QE('p24RenameFileButton', false);
                QE('p24SelectAllButton', false);
                Q('p24SelectAllButton').value = "Tout sélectionner";
                QE('p24RefreshButton', false);
                QE('p24CutButton', false);
                QE('p24CopyButton', false);
                QE('p24PasteButton', false);
            } else {
                var cc = p24getFileSelCount(), tc = p24getFileCount(), sfc = p24getFileSelCount(false); // In order: number of entires selected, number of total entries, number of selected entires that are files (not folders)
                var winAgent = (webRtcDesktop.platform == 'win32');
                QE('p24DeleteFileButton', (cc > 0) && ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24NewFolderButton', ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24UploadButton', ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24RenameFileButton', (cc == 1) && ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24SelectAllButton', tc > 0);
                Q('p24SelectAllButton').value = (cc > 0 ? "Ne rien sélectionner" : "Tout sélectionner");
                QE('p24RefreshButton', true);
                QE('p24CutButton', (cc > 0) && (cc == sfc) && ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24CopyButton', (cc > 0) && (cc == sfc) && ((p24filetreelocation.length > 0) || (winAgent == false)));
                QE('p24PasteButton', ((p24filetreelocation.length > 0) || (winAgent == false)) && ((p24clipboard != null) && (p24clipboard.length > 0)));
            }
        }

        function p24getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == "3"))) cc++; } return cc; }
        function p24getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fd'); return checkboxes.length; }
        function p24selectallfile() { var nv = (p24getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p24setActions(); }
        function p24createfolder() { setDialogMode(11, "Nouveau dossier", 3, p24createfolderEx, '<input type=text id=p24renameinput maxlength=64 onkeyup=p24fileNameCheck(event) style=width:100% />'); focusTextBox('p24renameinput'); p24fileNameCheck(); }
        function p24createfolderEx() { p24files.sendCtrlMsg(JSON.stringify({ action: 'mkdir', reqid: 1, path: p24filetreelocation.join('/') + '/' + Q('p24renameinput').value })); p24folderup(999); }
        function p24deletefile() { var cc = p24getFileSelCount(); setDialogMode(11, "Supprimer", 3, p24deletefileEx, (cc > 1) ? ('Delete ' + cc + ' selected items?') : ('Delete selected item?')); }
        function p24deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(p24filetree.dir[checkboxes[i].value].n); } } p24files.sendCtrlMsg(JSON.stringify({ action: 'rm', reqid: 1, path: p24filetreelocation.join('/'), delfiles: delfiles })); p24folderup(999); }
        function p24renamefile() { var renamefile, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = p24filetree.dir[checkboxes[i].value].n; } } setDialogMode(11, "Renommer", 3, p24renamefileEx, '<input type=text id=p24renameinput maxlength=64 onkeyup=p24fileNameCheck(event) style=width:100% value="' + renamefile + '" />', { action: 'rename', path: p24filetreelocation.join('/'), oldname: renamefile }); focusTextBox('p24renameinput'); p24fileNameCheck(); }
        function p24renamefileEx(b, t) { t.newname = Q('p24renameinput').value; p24files.sendCtrlMsg(JSON.stringify(t)); p24folderup(999); }
        function p24fileNameCheck(e) { var x = isFilenameValid(Q('p24renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e != null) && (e.keyCode == 24)) { dialogclose(1); } }
        function p24uploadFile() { setDialogMode(11, "Téléverser un fichier", 3, p24uploadFileEx, '<input type=file name=files id=p24uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p24uploadinput\')" />'); updateUploadDialogOk('p24uploadinput'); }
        function p24uploadFileEx() { p24doUploadFiles(Q('p24uploadinput').files); }
        function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }

        var p24clipboard = null, p24clipboardFolder = null, p24clipboardCut = 0;
        function p24copyFile(cut) { var checkboxes = document.getElementsByName('fd'); p24clipboard = []; p24clipboardCut = cut, p24clipboardFolder = p24targetpath; for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == "3")) { p24clipboard.push(p24filetree.dir[checkboxes[i].value].n); } } p24updateClipview(); }
        function p24pasteFile() { var x = ''; if ((p24clipboard != null) && (p24clipboard.length > 0)) { x = 'Confim ' + (p24clipboardCut == 0 ? 'copy' : 'move') + ' of ' + p24clipboard.length + ' entrie' + ((p24clipboard.length > 1) ? 's' : '') + ' to this location?' } setDialogMode(11, "Pâte", 3, p24pasteFileEx, x); }
        function p24pasteFileEx() { p24files.sendCtrlMsg(JSON.stringify({ action: (p24clipboardCut == 0 ? 'copy' : 'move'), reqid: 1, scpath: p24clipboardFolder, dspath: p24targetpath, names: p24clipboard })); p24folderup(999); if (p24clipboardCut == 1) { p24clipboard = null, p24clipboardFolder = null, p24clipboardCut = 0; p24updateClipview(); } }
        function p24updateClipview() { var x = ''; if ((p24clipboard != null) && (p24clipboard.length > 0)) { x = 'Holding ' + p24clipboard.length + ' entrie' + ((p24clipboard.length > 1) ? 's' : '') + ' for ' + (p24clipboardCut == 0 ? 'copy' : 'move') + ', <a onclick=p24clearClip() style=cursor:pointer>Clear</a>.' } QH('p24bottomstatus', x); p24setActions(); }
        function p24clearClip() { p24clipboard = null; p24clipboardFolder = null; p24clipboardCut = 0; p24updateClipview(); }

        function p24fileDragDrop(e) {
            haltEvent(e);
            QV('p24bigfail', false);
            QV('p24bigok', false);
            if (e.dataTransfer == null || e.dataTransfer.files.length == 0 || p24filetree == null) return;
            if ((p24filetreelocation.length == 0) && (webRtcDesktop.platform == 'win32')) return // If this is Windows, do not accept files in the root folder
            p24doUploadFiles(e.dataTransfer.files);
        }

        var p24dragtimer = null;
        function p24fileDragOver(e) {
            haltEvent(e);
            if (p24dragtimer != null) { clearTimeout(p24dragtimer); p24dragtimer = null; }
            var ac = (p24filetree != null); // Set to true if we can accept the file
            if ((p24filetreelocation.length == 0) && (webRtcDesktop.platform == 'win32')) { ac = false; } // If this is Windows, do not accept files in the root folder
            QV('p24bigok', ac);
            QV('p24bigfail', !ac);
        }

        function p24fileDragLeave(e) {
            haltEvent(e);
            if (e.target.id != "p24filetable") {
                QV('p24bigfail', false);
                QV('p24bigok', false);
            } else {
                p24dragtimer = setTimeout(function () { QV('p24bigfail', false); QV('p24bigok', false); p24dragtimer = null; }, 200);
            }
        }

        function getFileSizeStr(size) { if (size == 1) return "1 octet"; return format("{0} octets", size); }
        function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
        var isFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); } })();
        function focusTextBox(x) { setTimeout(function () { Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }


        //
        // FILES DOWNLOAD
        //

        var downloadFile; // Global state for file download

        // Called by the html page to start a download, arguments are: path, file name and file size.
        function p24downloadfile(x, y, z) {
            if (xxdialogMode || downloadFile || !p24files) return;
            downloadFile = { path: decodeURIComponent(x), file: decodeURIComponent(y), size: z, tsize: 0, data: '', state: 0, id: Math.random() }
            //console.log('p24downloadFileCancel', downloadFile);
            p24files.sendCtrlMsg(JSON.stringify({ action: 'download', sub: 'start', id: downloadFile.id, path: downloadFile.path }));
            setDialogMode(11, "Télécharger un fichier", 10, p24downloadFileCancel, '<div>' + downloadFile.file + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=' + z + ' />');
        }

        // Called by the html page to cancel the download
        function p24downloadFileCancel() { if (downloadFile != null) { setDialogMode(0); if (p24files != null) { p24files.sendCtrlMsg(JSON.stringify({ action: 'download', sub: 'cancel', id: downloadFile.id })); } downloadFile = null; } }

        // Called by the transport when download control command is received
        function p24gotDownloadCommand(cmd) {
            //console.log('p24gotDownloadCommand', cmd);
            if ((downloadFile == null) || (cmd.id != downloadFile.id)) return;
            if (cmd.sub == 'start') { downloadFile.state = 1; p24files.sendCtrlMsg(JSON.stringify({ action: 'download', sub: 'startack', id: downloadFile.id })); }
            else if (cmd.sub == 'cancel') { downloadFile = null; setDialogMode(0); }
        }

        // Called by the transport when binary data is received
        function p24gotDownloadBinaryData(data) {
            if (!downloadFile || downloadFile.state == 0) return;
            try { data = atob(data); } catch (ex) { return; }
            if ((data == null) || (data.length < 4)) return;
            if (data.length > 4) {
                downloadFile.tsize += data.length - 4; // Add to the total bytes received
                downloadFile.data += data.substring(4); // Append the data, decode Base64
                Q('d2progressBar').value = downloadFile.tsize; // Change the progress bar
            }
            if ((ReadInt(data, 0) & 1) != 0) { // Check end flag
                saveAs(data2blob(downloadFile.data), downloadFile.file); downloadFile = null; setDialogMode(0); // Save the file
            } else {
                p24files.sendCtrlMsg(JSON.stringify({ action: 'download', sub: 'ack', id: downloadFile.id })); // Send the ACK
            }
        }

        //
        // FILES UPLOAD
        //

        var uploadFile;

        function p24doUploadFiles(files) {
            if (xxdialogMode) return;
            uploadFile = { xpath: p24filetreelocation.join('/'), xfiles: files, xfilePtr: -1 };
            setDialogMode(11, "Téléverser un fichier", 10, p24uploadFileCancel, '<div id=p24dfileName>' + "Mise en place ..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />', 99);
            p24uploadNextFile();
        }

        // Push the next file
        function p24uploadNextFile() {
            uploadFile.xfilePtr++;
            if (uploadFile.xfiles.length > uploadFile.xfilePtr) {
                uploadFile.xptr = 0;
                var file = uploadFile.xfiles[uploadFile.xfilePtr];
                QH('p24dfileName', file.name);
                Q('d2progressBar').max = file.size;
                Q('d2progressBar').value = 0;
                uploadFile.xreader = new FileReader();
                uploadFile.xreader.onload = function () {
                    uploadFile.xdata = uploadFile.xreader.result;
                    p24files.sendCtrlMsg(JSON.stringify({ action: 'upload', sub: 'start', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
                };
                uploadFile.xreader.onerror = function () { p24uploadNextFile(); }
                uploadFile.xreader.readAsArrayBuffer(file);
            } else {
                p24uploadFileCancel();
                p24folderup(9999); // Refresh the file view
            }
        }

        // Used to cancel the entire transfer, close the upload dialog box
        function p24uploadFileCancel(button, tag) {
            if (uploadFile != null) {
                uploadFile = null;
                setDialogMode(0);
                if ((tag == 99) && (p24files != null)) { p24files.sendCtrlMsg(JSON.stringify({ action: 'upload', sub: 'cancel' })); }
            }
        }

        // Receive upload ack from the mesh agent, use this to keep sending more data
        function p24gotUploadData(cmd) {
            if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; }
            if (cmd.sub == 'start') {
                p24uploadNextPart(false);
                for (var i = 0; i < 8; i++) { p24uploadNextPart(true); } // Send 8 more blocks of 4 k to full the websocket.
            } else if (cmd.sub == 'ack') {
                p24uploadNextPart(false);
            } else if (cmd.sub == 'error') {
                p24uploadFileCancel();
            }
        }

        function ab2str(buf) { return String.fromCharCode.apply(null, new Uint8Array(buf)); }

        // Push the next part of the file into the websocket. If dataPriming is true, push more data only if it's not the last block of the file.
        function p24uploadNextPart(dataPriming) {
            var data = uploadFile.xdata, start = uploadFile.xptr, end = uploadFile.xptr + 4096;
            if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
            if (start == data.byteLength) {
                p24uploadNextFile();
            } else {
                p24files.sendCtrlMsg(btoa(IntToStr((end != data.byteLength) ? 0x01000000 : 0x01000001) + ab2str(data.slice(start, end))));
                uploadFile.xptr = end;
                Q('d2progressBar').value = end;
            }
        }

        // ###END###{DesktopInbandFiles}
        // ###END###{Desktop}

        //
        // Remote IDER
        //

        // ###BEGIN###{IDER}

        var ider;
        var iderCodeBlock;
        var iderTimer;

        // ###BEGIN###{IDER-IMRSDK}
        function iderStartIMR() {
            // Setup the IDER session (NodeJS with IMRSDK.dll)
            iderStop();
            ider = CreateAmtRemoteIderIMR();
            if (ider == null) return;
            ider.digestRealmMatch = wsstack.comm.digestRealm;
            ider.onStateChanged = onIderStateChange;
            ider.m.onDialogPrompt = onIderDialogPrompt;

            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                ider.m.Start(currentcomputer._id, 16992, 'x', 'x', 0, wsstack.comm, meshCentralServer);
            } else {
                // ###END###{MeshServerConnect}
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                ider.m.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], amtstack.wsman.comm.xtlsCertificate, wsstack.comm.xtlsoptions);
                // ###BEGIN###{MeshServerConnect}
            }
            // ###END###{MeshServerConnect}

            QV('IDERDiskMapButton', false); // Hide the disk heat map button since it's not supported.
        }

        function onIderSourceChange() {
            var sel = Q('storagesourceoption').value;
            QV('iderisofile', (sel & 1) == 0);
            QV('iderimgfile', (sel & 2) == 0);
            QV('iderisodrive', (sel & 1) != 0);
            QV('iderimgdrive', (sel & 2) != 0);
        }
        // ###END###{IDER-IMRSDK}

        function iderStart(e) {
            if (xxdialogMode) return;
            // ###BEGIN###{IDER-IMRSDK}
            if ((e.shiftKey != true) && (require('os').platform() == 'win32')) { iderStartIMR(); return; }
            // ###END###{IDER-IMRSDK}

            // Setup the IDER session (WebSocket)
            var x = '<div>' + "Montez des images de disque sur un ordinateur Intel&reg; AMT - Expérimental." + '</div><br />';
            x += '<div style=height:26px><input id=floppyImageInput type=file style=float:right;width:250px accept=".img"><div>' + NoBreak("Disquette (.img)") + '</div></div>';
            x += '<div style=height:26px><input id=cdromImageInput type=file style=float:right;width:250px accept=".iso"><div>' + NoBreak("CD-ROM (.iso)") + '</div></div>';
            x += '<div style=height:26px><select id=iderStartType style=float:right;width:250px><option value=0>' + "Au prochain démarrage" + '<option value=1>' + "Gracieux" + '<option value=2>' + "Immédiat" + '</select><div>' + "Début de session" + '</div></div>';
            setDialogMode(11, "Redirection de stockage", 3, iderStart2, x);
            var iderurl = null;
            try { iderurl = localStorage.getItem('iderurl'); } catch (ex) { }
            if (iderurl) { Q('storageserverurl').value = iderurl.substring(1, iderurl.length - 1); }
        }

        function iderStart2() {
            // Check the files
            if ((Q('floppyImageInput').files.length != 1) && (Q('cdromImageInput').files.length != 1)) { messagebox("Erreur de redirection de stockage", "Au moins un fichier d'image disque doit être sélectionné."); return; }
            if ((Q('floppyImageInput').files.length == 1) && ((Q('floppyImageInput').files[0].size % 512) != 0)) { messagebox("Erreur de redirection de stockage", "Fichier .img non valide."); return; }
            if ((Q('cdromImageInput').files.length == 1) && ((Q('cdromImageInput').files[0].size % 2048) != 0)) { messagebox("Erreur de redirection de stockage", "Fichier .iso non valide."); return; }

            // Fetch the files
            var floppy = null, cdrom = null;
            if (Q('floppyImageInput').files.length == 1) { floppy = Q('floppyImageInput').files[0]; }
            if (Q('cdromImageInput').files.length == 1) { cdrom = Q('cdromImageInput').files[0]; }
            if ((floppy != null) || (cdrom != null)) { iderStart3(floppy, cdrom, Q('iderStartType').value); }
        }

        function iderStart3(floppy, cdrom, iderStart) {
            // Setup the IDER session
            iderStop();
            ider = CreateAmtRedirect(CreateAmtRemoteIder());
            ider.onStateChanged = onIderStateChange;
            ider.m.floppy = floppy;
            ider.m.cdrom = cdrom;
            ider.m.iderStart = iderStart;
            // ###BEGIN###{ComputerSelector}
            ider.digestRealmMatch = wsstack.comm.digestRealm;
            // ###END###{ComputerSelector}
            // ###BEGIN###{IDERStats}
            ider.m.sectorStats = iderSectorStats;
            // ###END###{IDERStats}

            // ###BEGIN###{Mode-MeshCentral2}
            ider.tlsv1only = amtstack.wsman.comm.tlsv1only;
            ider.Start(currentMeshNode._id, 16994, '*', '*', 0);
            // ###END###{Mode-MeshCentral2}
            // ###BEGIN###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-Firmware}
            ider.Start();
            // ###END###{Mode-Firmware}
            // ###BEGIN###{!Mode-Firmware}
            ider.tlsv1only = amtstack.wsman.comm.tlsv1only;
            // ###BEGIN###{MeshServerConnect}
            if (meshCentralServer != null) {
                desktop.Start(currentcomputer._id, 0, 'x', 'x', 0, wsstack.comm, meshCentralServer);
            } else {
            // ###END###{MeshServerConnect}
                var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
                // ###BEGIN###{!Mode-NodeWebkit}
                ider.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls']);
                // ###END###{!Mode-NodeWebkit}
                // ###BEGIN###{Mode-NodeWebkit}
                ider.Start(ports.host, ports.redir, amtstack.wsman.comm.user, amtstack.wsman.comm.pass, currentcomputer['tls'], wsstack.comm.getPeerCertificateFingerprint(), wsstack.comm.xtlsoptions);
                // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{MeshServerConnect}
            }
            // ###END###{MeshServerConnect}
            // ###END###{!Mode-Firmware}
            // ###END###{!Mode-MeshCentral2}

            QV('IDERDiskMapButton', true); // Show the disk heat map button since it is supported.
        }

        function iderStop() {
            // Stop the IDER session
            if (ider) { ider.m.Stop(); ider.onStateChanged = null; ider.m.onDialogPrompt = null; delete ider; }
            if (iderTimer) { clearInterval(iderTimer); delete iderTimer; }
            // ###BEGIN###{IDERStats}
            iderToggleDiskMap(false);
            // ###END###{IDERStats}
        }

        function onIderStateChange(stack, state) {
            QE('idx_IDER1', state != 3);
            QE('idx_IDER2', state != 3);
            // ###BEGIN###{Mode-MeshCentral2}
            QE('idx_SIDER1', state != 3);
            QE('idx_SIDER2', state != 3);
            // ###END###{Mode-MeshCentral2}

            QV('id_iderstatus', state == 3); center();
            if (state == 3) {
                if (!urlvars['norefresh']) { iderTimer = setInterval(onIderTimer, 500); }
                onIderTimer();
            } else {
                if (iderTimer) { clearInterval(iderTimer); delete iderTimer; }
            }
        }

        function onIderTimer() {
            if (ider.m.Update) { ider.m.Update(); }
            if (ider.m.bytesFromAmt == -1) { iderStop(); } else { QH('id_iderstatusstr', '<b>' + (ider.m.server?"Serveur":'') + "Session IDE-R </b>, Connecté," + ider.m.bytesFromAmt + " dans," + ider.m.bytesToAmt + " en dehors."); }
        }

        // ###BEGIN###{IDERStats}
        var heatMapWidth = 600;
        var heatMapDividor = {};
        function iderSectorStats(mode, dev, total, start, len) {
            var canvas = dev ? Q('cdromHeatMapCanvas') : Q('floppyHeatMapCanvas');
            var ctx = canvas.getContext('2d');
            if (mode == 0) {
                heatMapDividor[dev] = 1;
                if (total > 0) { while ((total / heatMapDividor[dev]) > 8000) { heatMapDividor[dev] *= 2; } }
                if (dev) {
                    QV('cdromHeatMap', total)
                    QH('cdromHeatMapText', format("<b> CDROM </b>, les blocs font {0} octets.", (2048 * heatMapDividor[dev])));
                } else {
                    QV('floppyHeatMap', total);
                    QH('floppyHeatMapText', format("<b> Disquette </b>, les blocs font {0} octets.", (512 * heatMapDividor[dev])));
                }
            }
            var dividor = heatMapDividor[dev];
            total = total / dividor;
            start = start / dividor;
            len = len / dividor;
            var heatMapScale = 6;
            if (mode == 0) {
                canvas.height = ((Math.floor(total / (heatMapWidth / heatMapScale)) + ((total % heatMapWidth) ? 1 : 0)) * heatMapScale);
                ctx.fillStyle = 'rgba(225,250,225,1)';
                ctx.fillRect(0, 0, heatMapWidth, Math.floor(total / (heatMapWidth / heatMapScale)) * heatMapScale);
                if (total % heatMapWidth) { ctx.fillRect(0, Math.floor(total / (heatMapWidth / heatMapScale)) * heatMapScale, (total % (heatMapWidth / heatMapScale)) * heatMapScale, heatMapScale); }
                ctx.fillStyle = 'rgba(0,0,0,0.3)';
            } else {
                for (var i = start; i < start + len; i++) { sectorHeat(ctx, i, heatMapScale, dividor); }
            }
        }

        function sectorHeat(ctx, sector, scale, dividor) {
            ctx.fillRect((sector % (heatMapWidth / scale)) * scale, Math.floor(sector / (heatMapWidth / scale)) * scale, scale, scale);
        }

        function iderToggleDiskMap(x) {
            var visible = (QS('iderHeatmap').display != 'none');
            if (x == null) { x = !visible; }
            if (xxdialogMode) { x = false; }
            QS('iderHeatmap').display = x ? '' : 'none';
        }
        // ###END###{IDERStats}

        function onIderDialogPrompt(sender, args, buttons) {
            if (iderCodeBlock) { document.body.removeChild(iderCodeBlock); delete iderCodeBlock; }
            if (args['js']) { var JS = document.createElement('script'); JS.text = args['js']; iderCodeBlock = document.body.appendChild(JS); }
            setDialogMode(11, "Redirection de stockage", buttons ? buttons : 3, onIderDialogPromptOk, args['html']);
        }

        function onIderDialogPromptOk(button) {
            if (button == 1) {
                // ###BEGIN###{!Mode-NodeWebkit}
                if (window['iderServerCall']) { ider.m.dialogPrompt(window['iderServerCall']()); } else { ider.m.dialogPrompt(); }
                // ###END###{!Mode-NodeWebkit}
                // ###BEGIN###{Mode-NodeWebkit}
                ider.m.dialogPrompt(iderUserConsent);
                // ###END###{Mode-NodeWebkit}
            } else {
                iderStop();
            }
        }

        // ###BEGIN###{Mode-NodeWebkit}
        var restartIderFunction;
        function iderUserConsent(func) {
            restartIderFunction = func;
            amtstack.IPS_OptInService_StartOptIn(iderUserConsent2, 0, 1);
        }

        function iderUserConsent2(stack, name, response, status) {
            if (errcheck(status, stack)) return;
            //console.log("powerActionResponseC1(" + name + "," + response + "," + status + ")");
            if (response.Body['ReturnValue'] != 0) {
                messagebox("Erreur de consentement de l'utilisateur", response.Body.ReturnValueStr.replace(/_/g, ' '));
            } else {
                d6ConsentText.value = ''; // Reset user consent code to empty
                setDialogMode(6, "Consentement de l'utilisateur", 11, iderUserConsent3);
                checkConsentDisplay();
                consentChanged();
            }
        }

        function iderUserConsent3() {
            //console.log('IPS_OptInService_SendOptInCode()');
            amtstack.IPS_OptInService_SendOptInCode(d6ConsentText.value, iderUserConsent4, 0, 1);
        }

        function iderUserConsent4(stack, name, response, status) {
            if (errcheck(status, stack)) return;
            //console.log("powerActionResponseC2(" + name + "," + response + "," + status + ")");
            if (response.Body['ReturnValue'] != 0) {
                messagebox("Erreur de consentement de l'utilisateur", response.Body.ReturnValueStr.replace('_',' '));
            } else {
                restartIderFunction();
            }
        }
        // ###END###{Mode-NodeWebkit}

        // ###BEGIN###{Mode-MeshCentral2}

        // Server-side IDER
        function iderServerStart() {
            if (xxdialogMode) return;

            // Setup the IDER session (NodeJS)
            iderStop();
            ider = CreateAmtRemoteServerIder();
            if (ider == null) return;
            ider.onStateChanged = onIderStateChange;
            ider.m.sectorStats = iderSectorStats;
            ider.m.onDialogPrompt = onIderDialogPrompt;
            ider.tlsv1only = amtstack.wsman.comm.tlsv1only;
            ider.Start(currentMeshNode._id, 16994, '*', '*', 0);
        }

        // ###END###{Mode-MeshCentral2}

        // ###END###{IDER}

        // ###BEGIN###{RemoteAccess}

        //
        // Remote Access
        //

        var xxRemoteAccess = null;
        var xxEnvironementDetection = null;
        var xxCiraServers = null;
        var xxUserInitiatedCira = null;
        var xxUserInitiatedEnabledState = { 32768: "désactivé", 32769: "BIOS activé", 32770: "Activation du système d'exploitation", 32771: "BIOS et OS activés" };
        var xxRemoteAccessCredentiaLinks = null;
        var xxMPSUserPass = null;
        var xxPolicies = null;

        function PullRemoteAccess() {
            // We only deal with remote access starting with Intel AMT 6 and beyond
            // ###BEGIN###{Certificates}
            var requests = ['*AMT_EnvironmentDetectionSettingData', 'AMT_ManagementPresenceRemoteSAP', 'AMT_RemoteAccessCredentialContext', 'AMT_RemoteAccessPolicyAppliesToMPS', 'AMT_RemoteAccessPolicyRule', '*AMT_UserInitiatedConnectionService', 'AMT_MPSUsernamePassword'];
            // ###END###{Certificates}
            // ###BEGIN###{!Certificates}
            var requests = ['*AMT_EnvironmentDetectionSettingData', 'AMT_ManagementPresenceRemoteSAP', 'AMT_RemoteAccessCredentialContext', 'AMT_RemoteAccessPolicyAppliesToMPS', 'AMT_RemoteAccessPolicyRule', '*AMT_UserInitiatedConnectionService', 'AMT_MPSUsernamePassword', 'AMT_PublicKeyCertificate'];
            // ###END###{!Certificates}
            if (amtversion > 11) { requests.push('*IPS_HTTPProxyService', 'IPS_HTTPProxyAccessPoint'); }
            amtstack.BatchEnum(null, requests, processRemote1);
        }

        function processRemote1(stack, name, responses, status) {
            if ((amtversion > 11) && (status == 400)) {
                // Check if only the HTTP proxy objects failed
                status = 200;
                if (responses['IPS_HTTPProxyAccessPoint'].status == 400) { delete responses['IPS_HTTPProxyAccessPoint']; }
                if (responses['IPS_HTTPProxyService'].status == 400) { delete responses['IPS_HTTPProxyService']; }
                for (var i in responses) { if (responses[i].status != 200) { status = responses[i].status; } }
            }
            if (status == 400) return;
            if ((errcheck(status, stack)) || (responses['AMT_UserInitiatedConnectionService'] == undefined || responses['AMT_UserInitiatedConnectionService'].response == undefined)) return;
            QV('go17', true); // Remote Access
            xxRemoteAccess = responses;
            xxEnvironementDetection = responses['AMT_EnvironmentDetectionSettingData'].response;
            xxEnvironementDetection['DetectionStrings'] = MakeToArray(xxEnvironementDetection['DetectionStrings']);
            xxCiraServers = responses['AMT_ManagementPresenceRemoteSAP'].responses;
            xxUserInitiatedCira = responses['AMT_UserInitiatedConnectionService'].response;
            xxRemoteAccessCredentiaLinks = responses['AMT_RemoteAccessCredentialContext'].responses;
            xxMPSUserPass = responses['AMT_MPSUsernamePassword'].responses;

            // Figure out policies attached to servers. Create a policy type to server table.
            xxPolicies = { 'User': [], 'Alert': [], 'Periodic': [] };
            for (var i in responses['AMT_RemoteAccessPolicyAppliesToMPS'].responses) {
                var policy = responses['AMT_RemoteAccessPolicyAppliesToMPS'].responses[i];
                var server = Clone(getItem(xxCiraServers, 'Name', getItem(policy['ManagedElement']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'Name')['Value']));
                server.MpsType = policy['MpsType']; // MpsType was added in Intel AMT 11.6
                var ptype = (getItem(policy['PolicySet']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'PolicyRuleName')['Value']).split(' ')[0];
                xxPolicies[ptype].push(server);
            }

            updateRemoteAccess();
        }

        function updateRemoteAccess() {
            if (xxEnvironementDetection == null) return;
            var x = '', e = "désactivé", ciraProxySupport = (xxRemoteAccess['IPS_HTTPProxyService'] && xxRemoteAccess['IPS_HTTPProxyAccessPoint']);
            if (xxEnvironementDetection['DetectionStrings'] && xxEnvironementDetection['DetectionStrings'].length > 0) { e = "Activée," + xxEnvironementDetection['DetectionStrings'].length + ' ' + (xxEnvironementDetection['DetectionStrings'].length > 1?'domains':'domain'); }

            // General settings
            x += TableStart();
            x += TableEntry("Détection d'environnement", addLink(e, 'editEnvironmentDetection()'));
            x += TableEntry("Options d'initiation de l'utilisateur", addLinkConditional(xxUserInitiatedEnabledState[xxUserInitiatedCira['EnabledState']], 'editUserInitiatedCira()', xxAccountAdminName));
            var y = ('<i>' + "Aucun" + '</i>');
            if (xxPolicies['User'].length > 0) { y = ''; for (var i in xxPolicies['User']) { if (y.length > 0) y += ', '; y += xxPolicies['User'][i]['AccessInfo']; if (xxPolicies['User'][i].MpsType == 1) { y += ' (CILA)'; } } }
            x += TableEntry("Connexion initiée par l'utilisateur", addLinkConditional(y, 'editMpsPolicy("User")', xxAccountAdminName));
            var y = ('<i>' + "Aucun" + '</i>');
            if (xxPolicies['Alert'].length > 0) { y = ''; for (var i in xxPolicies['Alert']) { if (y.length > 0) y += ', '; y += xxPolicies['Alert'][i]['AccessInfo']; if (xxPolicies['Alert'][i].MpsType == 1) { y += ' (CILA)'; } } }
            x += TableEntry("Connexion lancée par l'alerte", addLinkConditional(y, 'editMpsPolicy("Alert")', xxAccountAdminName));
            var y = ('<i>' + "Aucun" + '</i>');
            if (xxPolicies['Periodic'].length > 0) { y = ''; for (var i in xxPolicies['Periodic']) { if (y.length > 0) y += ', '; y += xxPolicies['Periodic'][i]['AccessInfo']; if (xxPolicies['Periodic'][i].MpsType == 1) { y += ' (CILA)'; } } }
            var periodicPolicy = getItem(xxRemoteAccess['AMT_RemoteAccessPolicyRule'].responses, "PolicyRuleName", "Périodique");
            if (periodicPolicy) {
                var exdata = atob(periodicPolicy['ExtendedData']);
                if (ReadInt(exdata, 0) == 0) { y += format(", chaque {0} seconde", ReadInt(exdata, 4)); }
                if (ReadInt(exdata, 0) == 1) { var hours = ReadInt(exdata, 4); var minutes = ReadInt(exdata, 8); if (minutes < 10) minutes = '0' + minutes; y += ', at ' + hours + ":" + minutes + ' daily'; }
            }
            x += TableEntry("Connexion périodique", addLinkConditional(y, 'editMpsPolicy("Periodic")', xxAccountAdminName));
            x += TableEnd();

            // Show MPS servers
            x += '<br>';
            x += TableStart2();
            x += '<tr><td class=r1 style=padding-left:15px><br>' + "Gérez les serveurs de gestion à distance Intel&reg; AMT." + '<br><br>';
            if (xxCiraServers.length == 0) {
                x += '<div style=padding-left:15px><br><i>' + "Aucun serveur distant trouvé." + '</i></div><br>';
            } else {
                for (var i in xxCiraServers) {
                    var desc = ':' + xxCiraServers[i]['Port'];
                    if (xxCiraServers[i]['CN']) desc += ', ' + xxCiraServers[i]['CN'];
                    x += '<div class=itemBar onclick=showServerDetails(' + i + ')><div style=padding-top:3px><b>' + xxCiraServers[i]['AccessInfo'] + '</b>' + EscapeHtml(desc) + '</div></div>';
                }
            }

            // Show MPS proxies if supported
            if (ciraProxySupport) {
                x += '<br>' + "Gérez les proxys HTTP utilisés pour les connexions de gestion." + '<br><br>';
                var proxyService = xxRemoteAccess['IPS_HTTPProxyService'].response;
                var proxies = xxRemoteAccess['IPS_HTTPProxyAccessPoint'].responses;
                if (proxies.length == 0) {
                    x += '<div style=padding-left:15px><br><i>' + "Aucun proxy configuré." + '</i></div><br>';
                } else {
                    for (var i in proxies) {
                        //x += '<div class=itemBar onclick=showProxyDetails(' + i + ')><div style=padding-top:3px><b>' + EscapeHtml(proxies[i]['AccessInfo']) + ':' + proxies[i]['ProxyPort'] + '</b> / ' + EscapeHtml(proxies[i]['NetworkDnsSuffix']) + '</div></div>';
                        x += '<div class=itemBar onclick=showProxyDetails(' + i + ')><div style=padding-top:3px><b>' + EscapeHtml(proxies[i]['AccessInfo']) + ':' + proxies[i]['Port'] + '</b> / ' + EscapeHtml(proxies[i]['NetworkDnsSuffix']) + '</div></div>';
                    }
                }
            }

            var addserverbutton = '';
            if (xxAccountAdminName) {
                addserverbutton = AddButton("Ajouter un serveur ...", 'AddRemoteAccessServer()');
                if (ciraProxySupport) { addserverbutton += AddButton("Ajouter un proxy ...", 'AddRemoteAccessProxy()'); }
            }
            x += '<br><td class=r1>' + TableEnd(AddRefreshButton('PullRemoteAccess()') + addserverbutton);

            QH('id_TableRemoteAccess', x);
        }

        var xxEditMpsPolicyType;
        function editMpsPolicy(type) {
            var x = '', cilaSupport = ((amtversion > 11) || ((amtversion == 11) && (amtversionmin >= 6)));
            xxEditMpsPolicyType = type;
            var name = xxEditMpsPolicyType;
            if (name == 'User') name = "Initié par l'utilisateur";
            var policy = getItem(xxRemoteAccess['AMT_RemoteAccessPolicyRule'].responses, "PolicyRuleName", name);
            x += '<div style=height:26px><select id=d2server1 style=float:right;width:206px onchange=editMpsPolicyUpdate()>';
            x += '<option value=-1>' + "(Aucun)";
            for (var i in xxCiraServers) { x += '<option value=' + i + '' + ((xxPolicies[type][0] && xxPolicies[type][0]['Name'] == xxCiraServers[i]['Name']) ? ' selected' : '') + '>' + xxCiraServers[i]['AccessInfo'] }
            x += '</select><div>' + "Serveur principal" + '</div></div>';
            if (cilaSupport) { x += '<div style=height:26px><select id=d2server1cira style=float:right;width:206px onchange=editMpsPolicyUpdate()><option value=0>' + "ACEI - Externe" + '<option value=1' + (((xxPolicies[type][0]) && (xxPolicies[type][0].MpsType == 1))?' selected':'') + '>' + "CILA - Interne" + '</select><div>' + "Type MPS principal" + '</div></div>'; }
            if (xxCiraServers.length > 1) {
                x += '<div style=height:26px><select id=d2server2 style=float:right;width:206px onchange=editMpsPolicyUpdate()>';
                x += '<option value=-1>' + "(Aucun)";
                for (var i in xxCiraServers) { x += '<option value=' + i + '' + ((xxPolicies[type][1] && xxPolicies[type][1]['Name'] == xxCiraServers[i]['Name']) ? ' selected' : '') + '>' + xxCiraServers[i]['AccessInfo'] }
                x += '</select><div>' + "Serveur secondaire" + '</div></div>';
                if (cilaSupport) { x += '<div style=height:26px><select id=d2server2cira style=float:right;width:206px onchange=editMpsPolicyUpdate()><option value=0>' + "ACEI - Externe" + '<option value=1' + (((xxPolicies[type][1]) && (xxPolicies[type][1].MpsType == 1)) ? ' selected' : '') + '>' + "CILA - Interne" + '</select><div>' + "Type MPS secondaire" + '</div></div>'; }
            }
            var t, v = 0;
            if (policy) { v = policy['TunnelLifeTime']; }
            x += '<div style=height:26px><input id=d2lifetime style=float:right;width:200px onchange=editMpsPolicyUpdate() value=' + v + '>';
            x += '<div>' + "Durée de vie du tunnel (secondes)" + '</div></div>';
            if (type == 'Periodic') {
                t = 0;
                v = 3600;
                if (policy) {
                    var xx = atob(policy['ExtendedData']);
                    t = ReadInt(xx, 0);
                    v = ReadInt(xx, 4);
                    if (t == 1) {
                        var mm = ReadInt(xx, 8);
                        if (mm < 10) mm = '0' + mm;
                        v += ':' + mm;
                    }
                }
                x += '<div style=height:26px><select id=d2ttype style=float:right;width:206px onchange=editMpsPolicyUpdate()>';
                x += '<option value=0' + (t == 0 ? ' selected' : '') + '>' + "Périodique, intervalle de temps" + '<option value=1' + (t == 1 ? ' selected' : '') + '>' + "Moment de la journée, une fois par jour";
                x += '</select><div>' + "Type de déclencheur" + '</div></div><div style=height:26px><input id=d2timer style=float:right;width:200px onkeyup=editMpsPolicyUpdate() value=' + v + '><div id=ttypelabel></div></div>';
            }
            setDialogMode(11, format("{0} Connexion", type), 3, editMpsPolicyOk, x);
            editMpsPolicyUpdate();
        }

        function editMpsPolicyUpdate() {
            var cilaSupport = ((amtversion > 11) || ((amtversion == 11) && (amtversionmin >= 6)));
            var ok = (xxCiraServers.length <= 1 || ((Q('d2server1').value == -1) || (Q('d2server1').value != Q('d2server2').value)));
            if (ok == true && xxEditMpsPolicyType == 'Periodic' && Q('d2ttype').value == 1) { var hhmm = Q('d2timer').value.split(':'); if (hhmm.length != 2) ok = false; else { var hh = parseInt(hhmm[0]); var mm = parseInt(hhmm[1]); if (hh < 0 || hh > 23 || mm < 0 || mm > 59) ok = false; } }
            QE('idx_dlgOkButton', ok);
            if (xxCiraServers.length > 1) QE('d2server2', Q('d2server1').value != -1);
            if (xxEditMpsPolicyType == 'Periodic') {
                QE('d2timer', Q('d2server1').value != -1);
                QH('ttypelabel', Q('d2ttype').value == 0 ? "Intervalle de déclenchement (secondes)" : "Heure de la journée (HH: MM)");
                QE('d2ttype', Q('d2server1').value != -1);
            }
            QE('d2lifetime', Q('d2server1').value != -1);

            // If we are on Intel AMT 11.6 or higher, enable the CIRA/CILA selector when needed.
            if (cilaSupport) {
                QE('d2server1cira', Q('d2server1').value > -1)
                if (xxCiraServers.length > 1) { QE('d2server2cira', (Q('d2server1').value > -1) && (Q('d2server2').value > -1)); }
            }
        }

        function editMpsPolicyOk() {
            var name = xxEditMpsPolicyType;
            if (name == 'User') { name = 'User Initiated'; }

            if (getItem(xxRemoteAccess['AMT_RemoteAccessPolicyRule'].responses, 'PolicyRuleName', name)) {
                // Remove old policy
                amtstack.Delete('AMT_RemoteAccessPolicyRule', { 'PolicyRuleName': name }, editMpsPolicyOk2);
            } else {
                // No old policy to remove, skip this.
                editMpsPolicyOk2();
            }
        }

        function editMpsPolicyOk2(stack, name, responses, status) {
            var cilaSupport = ((amtversion > 11) || ((amtversion == 11) && (amtversionmin >= 6)));
            if (Q('d2server1').value == -1) { PullRemoteAccess(); return; }

            var trigger = 0;
            if (xxEditMpsPolicyType == 'Alert') trigger = 1;
            if (xxEditMpsPolicyType == 'Periodic') trigger = 2;

            // Setup extended data
            var extendedData = null;
            if (trigger == 2) {
                var timertype = Q('d2ttype').value;
                var exdata = IntToStr(Q('d2timer').value); // Interval trigger
                if (timertype == 1) { var hhmm = Q('d2timer').value.split(':'); exdata = IntToStr(parseInt(hhmm[0])) + IntToStr(parseInt(hhmm[1])); } // Time of day trigger
                extendedData = btoa(IntToStr(timertype) + exdata);
            }

            // Create the MPS server references
            var server1, server2;
            if (Q('d2server1').value >= 0) { server1 = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_ManagementPresenceRemoteSAP</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="Name">' + xxCiraServers[Q('d2server1').value]['Name'] + '</Selector></SelectorSet></ReferenceParameters>'; }
            if (Q('d2server1').value >= 0 && xxCiraServers.length > 1 && Q('d2server2').value >= 0) { server2 = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_ManagementPresenceRemoteSAP</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="Name">' + xxCiraServers[Q('d2server2').value]['Name'] + '</Selector></SelectorSet></ReferenceParameters>'; }

            // Put the CIRA/CILA servers in the right bins.
            var ciraServers = [];
            var cilaServers = [];
            if (cilaSupport) {
                // Only Intel AMT 11.6 supports this
                if (server1) {
                    if (Q('d2server1cira').value == 0) { ciraServers.push(server1); } else { cilaServers.push(server1); }
                    if (server2) { if (Q('d2server2cira').value == 0) { ciraServers.push(server2); } else { cilaServers.push(server2); } }
                }
            } else {
                // If older than Intel AMT 11.6, put all servers in the CIRA bucket.
                if (server1) { ciraServers.push(server1); if (server2) { ciraServers.push(server2); } }
            }

            // Go ahead and create the new CIRA/CILA policy.
            amtstack.AMT_RemoteAccessService_AddRemoteAccessPolicyRule(trigger, Q('d2lifetime').value, extendedData, ciraServers, cilaServers, PullRemoteAccess);
        }

        var editEnvironmentDetectionTmp;
        function editEnvironmentDetection(a) {
            if (a != 1) { editEnvironmentDetectionTmp = (xxEnvironementDetection['DetectionStrings']) ? Clone(xxEnvironementDetection['DetectionStrings']) : []; }
            var x = '';
            if (xxAccountAdminName) x += "Entrez jusqu'à 5 suffixes de domaine intranet. Si l'ordinateur se trouve en dehors de ces domaines, les ports locaux Intel&reg; AMT seront fermés et les connexions au serveur distant seront actives." + '<br><br>';
            if (editEnvironmentDetectionTmp.length == 0) { x += '<i>' + "Aucun domaine intranet, détection de l'environnement désactivée." + '</i><br>'; }
            for (var i in editEnvironmentDetectionTmp) { x += '<div class=itemBar style=margin-right:0><div style=float:right>' + AddButton2("Retirer", 'editEnvironmentDetectionRemove(' + i + ')') + '</div><div style=padding-top:3px;max-width:260px;overflow:hidden title="' + editEnvironmentDetectionTmp[i] + '"><b>' + editEnvironmentDetectionTmp[i] + '</b></div></div>'; }
            if (xxAccountAdminName && editEnvironmentDetectionTmp.length < 5) { x += '<br><input id=edInput placeholder=intranet.org style=width:276px onkeyup=edInputChg() maxlength=63><input type=button id=edAdd value=Add style=width:80px;margin-left:5px onclick=editEnvironmentDetectionAdd()>'; }
            if (a == 1) QH('id_dialogOptions', x); else setDialogMode(11, "Détection d'environnement", xxAccountAdminName?3:1, editEnvironmentDetectionDlg, x);
            edInputChg();
        }

        function editEnvironmentDetectionDlg() {
            if (xxAccountAdminName) {
                var t = Clone(xxEnvironementDetection);
                t['DetectionStrings'] = editEnvironmentDetectionTmp;
                //console.log('AMT_EnvironmentDetectionSettingData', t);
                amtstack.Put('AMT_EnvironmentDetectionSettingData', t, editEnvironmentDetectionDlg2, 0, 1);
            }
        }

        function editEnvironmentDetectionDlg2(stack, name, response, status) {
            if (status != 200) { messagebox("Détection d'environnement", format("Échec de l'ajout du serveur, état {0}", status)); }
            else if ((response.Body['ReturnValue']) && (response.Body['ReturnValue'] != 0)) { messagebox("Détection d'environnement", response.Body.ReturnValueStr.replace(/_/g, ' ')); }
            else { PullRemoteAccess(); }
        }

        function edInputChg() {
            if (editEnvironmentDetectionTmp.length < 5) QE('edAdd', Q('edInput').value.length > 0);
        }

        function editEnvironmentDetectionAdd() {
            editEnvironmentDetectionTmp.push(Q('edInput').value);
            editEnvironmentDetection(1);
        }

        function editEnvironmentDetectionRemove(h) {
            editEnvironmentDetectionTmp.splice(h, 1);
            editEnvironmentDetection(1);
        }

        function editUserInitiatedCira() {
            if (xxdialogMode) return;
            var s = '';
            for (var i in xxUserInitiatedEnabledState) { s += '<input type=radio name=d11 id=wl' + i + ' value=' + i + ' ' + ((xxUserInitiatedCira['EnabledState'] == i) ? 'checked' : '') + '>' + xxUserInitiatedEnabledState[i] + '<br>'; }
            setDialogMode(11, "Tunnel initié par l'utilisateur", 3, editUserInitiatedCiraDlg, s);
        }

        function editUserInitiatedCiraDlg() { amtstack.AMT_UserInitiatedConnectionService_RequestStateChange(document.querySelector('input[name=d11]:checked').value, null, editUserInitiatedCiraDlg2); }
        function editUserInitiatedCiraDlg2(stack, name, response, status) { if (status == 200) { amtstack.Get('AMT_UserInitiatedConnectionService', editUserInitiatedCiraDlg3, 0, 1); } }
        function editUserInitiatedCiraDlg3(stack, name, response, status) { if (status == 200) { xxUserInitiatedCira = response.Body; updateRemoteAccess(); } }

        var xxShowServerDetailsHandle;
        function showServerDetails(h) {
            xxShowServerDetailsHandle = h;
            var server = xxCiraServers[h];
            var x = '';
            x += addHtmlValue("Nom d'accès", server['AccessInfo']);
            if (server['Port']) x += addHtmlValue("Port", server['Port']);
            if (server['CN']) x += addHtmlValue("Nom commun", server['CN']);

            var credentiallink = getElementWithContextSelectorValue(xxRemoteAccessCredentiaLinks, server['Name']);
            if (credentiallink) {
                var credentialselectorvalue = credentiallink['ElementInContext']['ReferenceParameters']['SelectorSet']['Selector']['Value'];
                if (credentialselectorvalue.indexOf('Username') > 0) {
                    x += addHtmlValue("type d'identification", "TLS utilisateur et passe / serveur");
                    x += addHtmlValue("ID distant", getInstance(xxMPSUserPass, credentialselectorvalue)['RemoteID']);
                } else {
                    x += addHtmlValue("type d'identification", "Certificat / TLS d'authentification mutuelle");
                    // ###BEGIN###{!Certificates}
                    var c = getInstance(xxRemoteAccess['AMT_PublicKeyCertificate'].responses, credentialselectorvalue);
                    // ###END###{!Certificates}
                    // ###BEGIN###{Certificates}
                    var c = getInstance(xxCertificates, credentialselectorvalue);
                    // ###END###{Certificates}
                    x += addHtmlValue("Nom du certificat", parseCertName(c['Subject'])['CN']);
                }
            }

            var buttons = 1;
            if (xxAccountAdminName) buttons = 5;
            setDialogMode(11, "Serveur distant #" + (h + 1), buttons, showServerDetailsOk, x);
        }

        function getElementWithContextSelectorValue(elements, value) {
            for (var i in elements) {
                elements[i]['ElementProvidingContext']['ReferenceParameters']['SelectorSet']['Selector'] = MakeToArray(elements[i]['ElementProvidingContext']['ReferenceParameters']['SelectorSet']['Selector']);
                for (var j in elements[i]['ElementProvidingContext']['ReferenceParameters']['SelectorSet']['Selector']) { if (elements[i]['ElementProvidingContext']['ReferenceParameters']['SelectorSet']['Selector'][j]['Value'] == value) return elements[i]; }
            }
            return null;
        }

        function showServerDetailsOk(r) {
            // Delete the selected CIRA server 
            if (r == 2) { amtstack.Delete('AMT_ManagementPresenceRemoteSAP', { 'Name': xxCiraServers[xxShowServerDetailsHandle]['Name'] }, showServerDetailsOk2); }
        }

        function showServerDetailsOk2(stack, name, responses, status) {
            if (status == 408) { messagebox("Suppression du serveur distant", "Impossible de supprimer le serveur, accès refusé."); } else { PullRemoteAccess(); }
        }

        function parseCertName(x) {
            var j, r = {}, xx = x.split(',');
            for (var i in xx) { j = xx[i].indexOf('='); r[xx[i].substring(0, j)] = xx[i].substring(j + 1); }
            return r;
        }
        
        function showProxyDetails(h) {
            var proxy = xxRemoteAccess['IPS_HTTPProxyAccessPoint'].responses[h];

            var x = addHtmlValue("Nom d'accès", proxy['AccessInfo'] + ':' + proxy['ProxyPort']);
            x += addHtmlValue("Suffex DNS", proxy['NetworkDnsSuffix']);
            //x += addHtmlValue("Proxy type", ['Administrator', 'Operating system'][proxy['ProxyType']]);
            x += addHtmlValue("Type de proxy", ['Administrator', 'Operating system'][proxy['Type']]);
            //x += addHtmlValue("Last time used", proxy['LastTimeUsed']);

            var buttons = 1;
            if (xxAccountAdminName) { buttons = 5; }
            setDialogMode(11, "Http proxy #" + (h + 1), buttons, showProxyDetailsOk, x, h);
        }

        function showProxyDetailsOk(r, h) {
            // Delete the selected proxy server
            var proxy = xxRemoteAccess['IPS_HTTPProxyAccessPoint'].responses[h];
            if (r == 2) { amtstack.Delete('IPS_HTTPProxyAccessPoint', { 'Name': proxy['Name'] }, showProxyDetailsOk2); }
        }

        function showProxyDetailsOk2(stack, name, responses, status) {
            if (status == 408) { messagebox("Suppression du proxy HTTP", "Impossible de supprimer le proxy HTTP, accès refusé."); } else { PullRemoteAccess(); }
        }

        function AddRemoteAccessProxy() {
            // AddRemoteAccessProxy Host name = 2, Ipv4 = 3, Ipv6 = 4
            var x = '<div style=height:26px><select id=d2type style=float:right;width:206px onchange=AddRemoteAccessProxyUpdate()><option value=2>' + "Nom d'hôte FQDN" + '<option value=3>' + "Adresse IPv4" + '<option value=4>' + "Adresse IPv6" + '</select><div>' + "Type de connexion" + '</div></div>';
            x += '<div style=height:26px><input id=d2host style=float:right;width:200px maxlength=255 onkeyup=AddRemoteAccessProxyUpdate()><div id=d2typespan></div></div>';
            x += '<div style=height:26px><input id=d2port onkeypress="return (event.charCode == 0 || (event.charCode >= 48 && event.charCode <= 57))" style=float:right;width:200px onkeyup=AddRemoteAccessProxyUpdate()><div>' + "Port" + '</div></div>';
            x += '<div style=height:26px><input id=d2domain style=float:right;width:200px maxlength=191 onkeyup=AddRemoteAccessProxyUpdate()><div>' + "Suffixe DNS" + '</div></div>';
            setDialogMode(11, "Ajouter un proxy HTTP", 3, AddRemoteAccessProxyOk, x);
            AddRemoteAccessProxyUpdate();
        }

        function AddRemoteAccessProxyUpdate() {
            var ok = (Q('d2host').value.length != 0) && (Q('d2domain').value.length != 0);
            if ((Q('d2port').value.length == 0) || (parseInt(Q('d2port').value) > 65535)) { ok = false; }
            QE('idx_dlgOkButton', ok);
            QH('d2typespan', ['', '', "FQDN / nom d'hôte", "Adresse IPv4", "Adresse IPv6"][Q('d2type').value]);
        }

        function AddRemoteAccessProxyOk() {
            amtstack.IPS_HTTPProxyService_AddProxyAccessPoint(Q('d2host').value, Q('d2type').value, parseInt(Q('d2port').value), Q('d2domain').value, AddRemoteAccessProxyOk2);
        }

        function AddRemoteAccessProxyOk2(stack, name, response, status) {
            if (status != 200) {
                messagebox("Ajouter un serveur proxy", "Échec de l'ajout du proxy, état" + status);
            } else if (response.Body['ReturnValue'] != 0) {
                messagebox("Ajouter un serveur proxy", response.Body.ReturnValueStr.replace(/_/g, ' '));
            } else {
                PullRemoteAccess();
            }
        }

        function AddRemoteAccessServer() {
            // ###BEGIN###{!Certificates}
            var certs = xxRemoteAccess['AMT_PublicKeyCertificate'].responses;
            // ###END###{!Certificates}
            // ###BEGIN###{Certificates}
            var certs = [];
            for (var i in xxCertificates) { if (xxCertificates[i].XPrivateKey) { certs.push(xxCertificates[i]); } }
            // ###END###{Certificates}
            var x = '';
            x += '<div style=height:26px><select id=d2type style=float:right;width:206px onchange=AddRemoteAccessServerUpdate()><option value=201>' + "Nom d'hôte FQDN" + '<option value=3>' + "Adresse IPv4" + '</select><div>' + "Type de connexion" + '</div></div>';
            x += '<div style=height:26px><input id=d2name style=float:right;width:200px onkeyup=AddRemoteAccessServerUpdate()><div id=d2lname></div></div>';
            x += '<div style=height:26px><input id=d2port onkeypress="return (event.charCode == 0 || (event.charCode >= 48 && event.charCode <= 57))" style=float:right;width:200px value=4433 onkeyup=AddRemoteAccessServerUpdate()><div>' + "Port de serveur" + '</div></div>';
            x += '<div style=height:26px id=d2ucn><input id=d2cn style=float:right;width:200px onkeyup=AddRemoteAccessServerUpdate()><div>' + "Nom commun du serveur" + '</div></div>';
            x += '<div style=height:26px><select id=d2auth style=float:right;width:206px onchange=AddRemoteAccessServerUpdate()>';
            if (certs.length > 0) { x += '<option value=1>' + "Certificat"; }
            x += '<option value=2>' + "Identifiant Mot de passe" + '</select><div>' + "Type d'identification" + '</div></div>';
            x += '<span id=d2utype>';
            x += '<div style=height:26px><input id=d2user style=float:right;width:200px onkeyup=AddRemoteAccessServerUpdate()><div>' + "Nom d'utilisateur" + '</div></div>';
            x += '<div style=height:26px><input id=d2pass style=float:right;width:200px onkeyup=AddRemoteAccessServerUpdate()><div>' + "Mot de passe fort" + '</div></div>';
            x += '</span>';
            x += '<span id=d2ctype>';
            x += '<div style=height:26px><select id=d2cert style=float:right;width:206px onchange=AddRemoteAccessServerUpdate()>';
            for (var i in certs) { x += '<option value=' + certs[i]['InstanceID'].substring(34) + '>' + parseCertName(certs[i]['Subject'])['CN']; }
            x += '</select><div>' + "Certificat" + '</div></div></span>';
            setDialogMode(11, "Ajouter un serveur distant", 3, AddRemoteAccessServerOk, x);
            AddRemoteAccessServerUpdate();
        }

        function AddRemoteAccessServerOk() {
            var cref, user, pass, cn;
            if (Q('d2auth').value == 1) {
                cref = '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">Intel(r) AMT Certificate: Handle: ' + Q('d2cert').value + '</Selector></SelectorSet></ReferenceParameters>';
            } else {
                user = Q('d2user').value;
                pass = Q('d2pass').value;
            }
            if (Q('d2cn').value.length > 0) cn = Q('d2cn').value;
            amtstack.AMT_RemoteAccessService_AddMpServer(Q('d2name').value, Q('d2type').value, Q('d2port').value, Q('d2auth').value, cref, user, pass, cn, AddRemoteAccessServerOk2);
        }

        function AddRemoteAccessServerOk2(stack, name, response, status) {
            if (status != 200) {
                messagebox("Ajouter un serveur Internet", format("Échec de l'ajout du serveur, état {0}", status));
            } else if (response.Body['ReturnValue'] != 0) {
                messagebox("Ajouter un serveur Internet", response.Body.ReturnValueStr.replace(/_/g, ' '));
            } else {
                PullRemoteAccess();
            }
        }

        function AddRemoteAccessServerUpdate() {
            var ok = (Q('d2name').value.length != 0);
            if (Q('d2type').value == 3 && ok == true)  { ok = (Q('d2cn').value.length != 0); }
            if (Q('d2auth').value == 2 && ok == true) { ok = ((Q('d2user').value.length != 0) && (passwordcheck(Q('d2pass').value))); }
            if ((Q('d2port').value.length == 0) || (parseInt(Q('d2port').value) > 65535)) { ok = false; }
            if ((Q('d2name').value.indexOf(':') != -1) || ((Q('d2type').value == 3) && (Q('d2cn').value.indexOf(':') != -1))) { ok = false; }
            QH('d2lname', (Q('d2type').value == 201) ? "Nom d'hôte" : "Adresse IPv4");
            QV('d2utype', Q('d2auth').value == 2);
            QV('d2ucn', Q('d2type').value == 3);
            QV('d2ctype', Q('d2auth').value == 1);
            QE('idx_dlgOkButton', ok);
        }

        // ###END###{RemoteAccess}

        //
        // Edit Computer Name & DNS feature
        //

        function showEditNameDlg(x) {
            if (xxdialogMode) return;
            var t = amtsysstate['AMT_GeneralSettings'].response['HostName'], y = amtsysstate['AMT_GeneralSettings'].response['DomainName'];
            if (y != null && y.length > 0) t += '.' + y;
            var r = '<br><div style=height:26px><input id=d11name value="' + t + '" style=float:right;width:200px><div>' + "Nom et domaine" + '</div></div>';
            if (x == 1) {
                var s = (amtsysstate['AMT_GeneralSettings'].response['SharedFQDN'] == true);
                r += '<div style=height:26px><select id=d11fqdn style=float:right;width:200px><option value=true ' + (s?'selected':'') + '>' + "Partagé, comme OS" + '<option value="false" ' + (s?'':'selected') + '>' + "Dédié, différent de l'OS" + '</select><div>' + "Partage de noms" + '</div></div>';
            }
            setDialogMode(11, "Nom de l'ordinateur", 3, editNameDlgOk, r);
        }

        function editNameDlgOk() {
            var i = Q('d11name').value, j = i.indexOf('.'), k = '';
            if (j >= 0) { k = i.substring(j + 1); i = i.substring(0, j); }
            var clone = Clone(amtsysstate['AMT_GeneralSettings'].response);
            clone['HostName'] = i;
            clone['DomainName'] = k;
            if (Q('d11fqdn')) { clone['SharedFQDN'] = d11fqdn.value; }
            amtstack.Put('AMT_GeneralSettings', clone, function() { amtstack.Get('AMT_GeneralSettings', computerNameGet, 0, 1); }, 0, 1);
        }

        function computerNameGet(stack, name, response, status) {
            if (status == 200) { amtsysstate['AMT_GeneralSettings'].response = response.Body; updateSystemStatus(); }
        }

        function showEditDnsDlg() {
            if (xxdialogMode) return;
            var g = amtsysstate['AMT_GeneralSettings'].response;
            var v = 0;
            if (g['DDNSUpdateByDHCPServerEnabled'] == true) v = 1;
            if (g['DDNSUpdateEnabled'] == true) v = 2;
            idx_d23ddns.value = v;
            idx_d23interval.value = g['DDNSPeriodicUpdateInterval'];
            idx_d23ttl.value = g['DDNSTTL'];
            showEditDnsDlgChange();
            setDialogMode(23, "Client DNS dynamique", 3, showEditDnsDlgOk);
        }

        function showEditDnsDlgOk() {
            var clone = Clone(amtsysstate['AMT_GeneralSettings'].response);
            clone['DDNSUpdateEnabled'] = ((idx_d23ddns.value == 2)?true:false);
            clone['DDNSUpdateByDHCPServerEnabled'] = ((idx_d23ddns.value == 1)?true:false);
            if (idx_d23ddns.value == 2) {
                clone['DDNSPeriodicUpdateInterval'] = idx_d23interval.value;
                clone['DDNSTTL'] = idx_d23ttl.value;
            }
            amtstack.Put('AMT_GeneralSettings', clone, function() { amtstack.Get('AMT_GeneralSettings', computerNameGet, 0, 1); }, 0, 1);
        }

        function showEditDnsDlgChange() {
            QE('idx_d23interval', idx_d23ddns.value == 2);
            QE('idx_d23ttl', idx_d23ddns.value == 2);
        }

        //
        // Intel AMT Features
        //

        function showFeaturesDlg() {
            if (xxdialogMode || !xxAccountAdminName) return;
            idx_d9redir.checked = amtfeatures[0], idx_d9kvm.checked = amtfeatures[3], idx_d9ider.checked = amtfeatures[2], idx_d9sol.checked = amtfeatures[1];
            QV('idx_d9kvm_div', amtfeatures[3] != null);
            setDialogMode(9, "Caractéristiques Intel&reg; AMT", 3, featuresDlgOk)
        }

        function featuresDlgOk() {
            var r = amtsysstate['AMT_RedirectionService'].response;
            r['ListenerEnabled'] = idx_d9redir.checked;
            r['EnabledState'] = 32768 + ((idx_d9ider.checked?1:0) + (idx_d9sol.checked?2:0));
            amtstack.AMT_RedirectionService_RequestStateChange(r['EnabledState'],
                function (stack, name, response, status) {
                    if (status != 200) { messagebox("Erreur", "RedirectionService, erreur RequestStateChange" + status); return; }
                    if (amtfeatures[3] != null) {
                        amtstack.CIM_KVMRedirectionSAP_RequestStateChange((idx_d9kvm.checked) ? 2 : 3, 0,
                        function (stack, name, response, status) {
                            if (status != 200) { messagebox("Erreur", "KVMRedirectionSAP, erreur RequestStateChange" + status); return; }
                            amtstack.Put('AMT_RedirectionService', r, function (stack, name, response, status) {
                                if (status != 200) { messagebox("Erreur", "Erreur PUT de RedirectionService" + status); return; }
                                amtstack.Get('AMT_RedirectionService', featuresDlgGet1, 0, 1);
                                amtstack.Get('CIM_KVMRedirectionSAP', featuresDlgGet2, 0, 1)
                            }, 0, 1) }
                        );
                    }
                }
            );
        }

        function featuresDlgGet1(stack, name, response, status) {
            if (status == 200) { amtsysstate['AMT_RedirectionService'].response = response.Body; updateSystemStatus(); }
        }

        function featuresDlgGet2(stack, name, response, status) {
            if (status == 200) { amtsysstate['CIM_KVMRedirectionSAP'].response = response.Body; updateSystemStatus(); }
        }

        //
        // Intel AMT Boot Features
        //

        function showEnableBootServiceDlg() {
            if (xxdialogMode) return;
            if (amtsysstate['CIM_BootService'].response['EnabledState'] != null) {
                QV('d26rpediv', amtversion > 15);
                if (amtversion > 15) {
                    idx_d26rpe1.checked = (amtsysstate['CIM_BootService'].response['EnabledState'] & 2)
                    idx_d26rpe0.checked = !idx_d26rpe1.checked;
                }
                idx_d26ocr1.checked = (amtsysstate['CIM_BootService'].response['EnabledState'] & 1)
                idx_d26ocr0.checked = !idx_d26ocr1.checked;
            }
            setDialogMode(26, "Boot Features", 3, showEnableBootServiceDlgOk)
        }

        function showEnableBootServiceDlgOk() {
            var v = 32768 + parseInt(document.querySelector('input[name=d26a]:checked').value);
            if (amtversion > 15) { v += parseInt(document.querySelector('input[name=d26b]:checked').value); }
            amtstack.CIM_BootService_RequestStateChange(v, null, showEnableBootServiceDlgResponse, v);
        }

        function showEnableBootServiceDlgResponse(stack, name, response, status, tag) {
            if (status == 200) {
                if (response.Body['ReturnValueStr'] != 'SUCCESS') { messagebox("Boot Features Error", response.Body['ReturnValueStr']); }
                amtstack.Get('CIM_BootService', showEnableBootServiceDlgResponse2, tag);
                PullSystemStatus();
            } else {
                if (response.Header['WsmanError']) {
                    messagebox("Boot Features Error", response.Header['WsmanError'].replace(/_/g, ' '));
                } else {
                    messagebox("Boot Features Error", "Error, Status = " + status);
                }
            }
        }

        function showEnableBootServiceDlgResponse2(stack, name, response, status, tag) {
            if ((status == 200) && (response.Body['EnabledState'] != tag)) { messagebox("Boot Features Error", "Unable to set OCR/RPE, check that these features are enabled in BIOS."); }
        }

        //
        // Intel AMT User Consent
        //

        function showConsentDlg() {
            if (xxdialogMode) return;
            var optinrequired = amtsysstate['IPS_OptInService'].response['OptInRequired'];
            idx_d10none.checked = (optinrequired == 0);
            idx_d10kvm.checked = (optinrequired == 1);
            idx_d10all.checked = (optinrequired == 0xFFFFFFFF);
            setDialogMode(10, "Consentement de l'utilisateur", 3, consentDlgOk)
        }

        function consentDlgOk() {
            amtsysstate['IPS_OptInService'].response['OptInRequired'] = document.querySelector('input[name=d10]:checked').value;
            amtstack.Put('IPS_OptInService', amtsysstate['IPS_OptInService'].response, function() { amtstack.Get('IPS_OptInService', consentGet, 0, 1); }, 0, 1);
        }

        function consentGet(stack, name, response, status) {
            if (status == 200) { PullSystemStatus(); }
        }

        //
        // NETWORK SETTINGS
        //

// ###BEGIN###{NetworkSettings}

        /*
        IPv6 %AddrType%:
            0 - Address generated from: fe80::/64 + Interface ID,
            1 - Address generated from: [Router advertised prefix] + [Interface ID],
            2 - Global IPv6 address obtained from DHCPv6 Server,
            3 - IPv6 unicast address configured by the user,
            4 - Returned by FW for IPv6 addresses that are not owned by FW (such as IPv6 router address, configuration server address etc.)

        IPv6 %AddrState%:
            0 - DAD is still in process for this address,
            1 - Address is valid and may be used for new communication,
            2 - Address is deprecated and should not be used for new communication,
            3 - Covers both the preferred and deprecated states,
            4 - The valid lifetime of the address has expired,
            5 - An interface ID collision has been detected for this address when performing DAD,
            6 - Returned by FW for IPv6 addresses that are not owned by FW (such as IPv6 router address, configuration server address etc.
        */
        // ipv6addrtype are element 0 to 4, ipv6addrstate are 5 and after. Merged both arrays to cut down size
        var ipv6addrtype = ["Lier l'adresse locale", "Adresse locale du réseau", "Adresse globale", "Configuré par l'utilisateur", "Interdit", "DAD en cours", "valide", "obsolète", "préféré / déconseillé", "expiré", "collision", "interdit"];
        function showIPv6AddrDlg(netifid, addrstr) {
            if (xxdialogMode) return;
            var x = TableStart();
            t = addrstr.split(',');
            for (var i = 0; i < t.length; i += 3) {
                x += TableEntry('<b>' + t[i] + '</b><br><span style=font-size:10px>' + ipv6addrtype[t[i + 1]] + "," + ipv6addrtype[+t[i + 2] + 5] + '</span>', '');
            }
            setDialogMode(11, (netifid == 0 ? "Adresses IPv6 pour l'interface filaire" : "Adresses IPv6 pour l'interface sans fil"), 1, null, x + TableEnd());
        }

        function showIPv6StateDlg(netifid, state) {
            if (xxdialogMode || !amtsysstate) return;
            var zz = amtsysstate['IPS_IPv6PortSettings'].responses[netifid];
            ipv6manual = (netifid == 0 && (isIpAddress(zz['IPv6Address']) || isIpAddress(zz['DefaultRouter']) || isIpAddress(zz['PrimaryDNS']) || isIpAddress(zz['SecondaryDNS'])));

            QV('id_d21manualdiv', netifid == 0);
            QV('id_d21subnetdiv', false);
            QV('d21o0', true);
            QV('d21l0', true);
            QH('d21l0', "IPv6 désactivé");
            QH('d21l1', "IPv6 activé, automatique");
            QH('d21l2', "IPv6 activé, adresse automatique + manuelle");
            d21o0.checked = !state;
            d21o1.checked = state && !ipv6manual;
            d21o2.checked = state && ipv6manual;
            idx_d21address.value = isIpAddress(zz['IPv6Address'],'');
            idx_d21gateway.value = isIpAddress(zz['DefaultRouter'],'');
            idx_d21dns1.value = isIpAddress(zz['PrimaryDNS'],'');
            idx_d21dns2.value = isIpAddress(zz['SecondaryDNS'],'');
            setDialogMode(21, (netifid == 0 ? "Prise en charge IPv6 pour l'interface filaire" : "Prise en charge IPv6 pour l'interface sans fil"), 3, function () { showIPv6StateDlgOk(netifid) })
            updateIPSetupDlg();
        }

        function showIPv6StateDlgOk(netifid) {
            var selector = '<w:SelectorSet><w:Selector Name="InstanceID">Intel(r) IPS IPv6 Settings ' + netifid + '</w:Selector></w:SelectorSet>';
            var zz = amtsysstate['IPS_IPv6PortSettings'].responses[netifid];
            if (netifid == 0) { // We can only set IPv6 manual address for wired interface
                if (d21o1.checked) { // Fully automatic, clear all addresses
                    zz['IPv6Address'] = zz['DefaultRouter'] = zz['PrimaryDNS'] = zz['SecondaryDNS'] = '::';
                    amtstack.Put('IPS_IPv6PortSettings', zz, showIPv6StateDlgDone, null, 0, selector);
                }
                if (d21o2.checked) { // Manual, set addresses
                    zz['IPv6Address'] = (idx_d21address.value == '') ? '::' : idx_d21address.value.toLocaleLowerCase();
                    zz['DefaultRouter'] = (idx_d21gateway.value == '') ? '::' : idx_d21gateway.value.toLocaleLowerCase();
                    zz['PrimaryDNS'] = (idx_d21dns1.value == '') ? '::' : idx_d21dns1.value.toLocaleLowerCase();
                    zz['SecondaryDNS'] = (idx_d21dns2.value == '') ? '::' : idx_d21dns2.value.toLocaleLowerCase();
                    amtstack.Put('IPS_IPv6PortSettings', zz, showIPv6StateDlgDone, null, 0, selector);
                }
            }
            // This code enables/disables IPv6 for a given interface.
            var elementSettings = amtsysstate['CIM_ElementSettingData'].responses;
            for (var i = 0; i < elementSettings.length; i++) {
                if (elementSettings[i]['SettingData'] && elementSettings[i]['SettingData']['ReferenceParameters']['SelectorSet']['Selector']['Value'] == ('Intel(r) IPS IPv6 Settings ' + netifid)) {
                    var CreationClassName = getItem(elementSettings[i]['ManagedElement']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'CreationClassName').Value;
                    var DeviceID = getItem(elementSettings[i]['ManagedElement']['ReferenceParameters']['SelectorSet']['Selector'], '@Name', 'DeviceID').Value;
                    var selector2 = '<w:SelectorSet><w:Selector Name="ManagedElement"><a:EndpointReference xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' + CreationClassName + '</w:ResourceURI><w:SelectorSet><w:Selector Name="CreationClassName">' + CreationClassName + '</w:Selector><w:Selector Name="DeviceID">' + DeviceID + '</w:Selector><w:Selector Name="SystemCreationClassName">CIM_ComputerSystem</w:Selector><w:Selector Name="SystemName">Intel(r) AMT</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference></w:Selector><w:Selector Name="SettingData"><a:EndpointReference xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address><a:ReferenceParameters><w:ResourceURI>http://intel.com/wbem/wscim/1/ips-schema/1/IPS_IPv6PortSettings</w:ResourceURI><w:SelectorSet><w:Selector Name="InstanceID">Intel(r) IPS IPv6 Settings ' + netifid + '</w:Selector></w:SelectorSet></a:ReferenceParameters></a:EndpointReference></w:Selector></w:SelectorSet>';
                    var clone = Clone(elementSettings[i]);
                    clone['IsCurrent'] = ((d21o0.checked) ? 2 : 1);
                    amtstack.Put('CIM_ElementSettingData', clone, showIPv6StateDlgDone, null, 0, selector2);
                }
            }
        }

        function showIPv6StateDlgDone(stack, name, response, status) {
            if (status == 200) {
                amtsysstate = undefined;
                PullSystemStatus();
            } else {
                messagebox("Prise en charge IPv6", format("Impossible de définir l'état IPv6, erreur {0}", status));
            }
        }

        function showPingActionDlg() {
            if (xxdialogMode) return;
            var g = amtsysstate['AMT_GeneralSettings'].response;
            var v = (g['PingResponseEnabled'] == true) + ((g['RmcpPingResponseEnabled'] == true) << 1);
            d20a.checked = (v == 0);
            d20b.checked = (v == 1);
            d20c.checked = (v == 2);
            d20d.checked = (v == 3);
            setDialogMode(20, "Réponse Intel&reg; AMT Ping", 3, showPingActionDlgOk);
        }

        function showPingActionDlgOk() {
            var clone = Clone(amtsysstate['AMT_GeneralSettings'].response);
            var v = document.querySelector('input[name=d20]:checked').value;
            clone['PingResponseEnabled'] = ((v & 1) != 0);
            clone['RmcpPingResponseEnabled'] = ((v & 2) != 0);
            amtstack.Put('AMT_GeneralSettings', clone, PullSystemStatus, 0, 1);
        }

        function showIPSetupDlg() {
            if ((xxdialogMode) || (amtsysstate == null)) return;
            var x = amtsysstate['AMT_EthernetPortSettings'].responses[0];
            QV('id_d21ipaddrsync', amtversion > 6);
            if (amtversion > 6) { Q('d21ipsync').checked = x['IpSyncEnabled']; };
            QV('id_d21manualdiv', true);
            QV('id_d21subnetdiv', true);
            QV('d21o0', false);
            QV('d21l0', false);
            QH('d21l1', "Configuration automatique à l'aide du serveur DHCP");
            QH('d21l2', "Configuration statique à l'aide des paramètres IPv4 ci-dessous");
            d21o1.checked = (x['DHCPEnabled'] == true);
            d21o2.checked = !d21o1.checked;
            idx_d21address.value = isIpAddress(x['IPAddress'],'');
            idx_d21subnet.value = isIpAddress(x['SubnetMask'],'');
            idx_d21gateway.value = isIpAddress(x['DefaultGateway'],'');
            idx_d21dns1.value = isIpAddress(x['PrimaryDNS'],'');
            idx_d21dns2.value = isIpAddress(x['SecondaryDNS'],'');
            updateIPSetupDlg();
            setDialogMode(21, "Paramètres IPv4", 3, showIPSetupDlgOk)
        }

        function updateIPSetupDlg() {
            var ok = true;
            if (d21o2.checked && (Q('d21l2').innerHTML == "IPv6 activé, adresse automatique + manuelle") && (idx_d21address.value.split(':').length < 2)) { ok = false; }
            QE('idx_dlgOkButton', ok);
            idx_d21address.disabled = idx_d21subnet.disabled = idx_d21gateway.disabled = idx_d21dns1.disabled = idx_d21dns2.disabled = !(d21o2.checked && ((amtversion < 7) || (Q('d21ipsync').checked == false)));
        }

        function showIPSetupDlgOk() {
            var x = Clone(amtsysstate['AMT_EthernetPortSettings'].responses[0]);
            x['DHCPEnabled'] = d21o1.checked;
            delete x['IPAddress'];
            delete x['SubnetMask'];
            delete x['DefaultGateway'];
            delete x['PrimaryDNS'];
            delete x['SecondaryDNS'];
            if (amtversion > 6) { x['IpSyncEnabled'] = Q('d21ipsync').checked; }
            if ((d21o1.checked == false) && (Q('d21ipsync').checked == false)) { // || (amtversion < 7)
                x['IPAddress'] = idx_d21address.value;
                x['SubnetMask'] = idx_d21subnet.value;
                x['DefaultGateway'] = idx_d21gateway.value;
                if (idx_d21dns1.value != '') x['PrimaryDNS'] = idx_d21dns1.value;
                if (idx_d21dns2.value != '') x['SecondaryDNS'] = idx_d21dns2.value;
            }
            amtstack.Put('AMT_EthernetPortSettings', x, showIPSetupDlgDone, 0, 1, x);
        }

        function showIPSetupDlgDone(stack, name, response, status) {
            if (status == 200) {
                amtsysstate = undefined;
                PullSystemStatus();
            } else {
                messagebox("Paramètres IPv4", format("Impossible de définir les paramètres réseau, erreur {0}", status));
            }
        }

// ###END###{NetworkSettings}

// ###BEGIN###{PowerControl}

        //
        // POWER ACTIONS
        //

        amtPowerBootCapabilities = null;
        function showPowerActionDlg() {
            if (xxdialogMode) return;
            statusbox("Actions de puissance", "Vérification des capacités ...");
            amtstack.Get('AMT_BootCapabilities', powerActionResponse00, 0, 1);
        }

        function showPowerActionDlg() {
            if (xxdialogMode) return;
            var powerState = 3;
            try {
                var x = amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'];
                if (x == 2) { powerState = 1; } else { powerState = 2; }
            } catch (ex) { }
            amtPowerBootCapabilities = amtsysstate['AMT_BootCapabilities'].response;
            QH('d5actionSelect', '');
            if (powerState & 2) { addOption('d5actionSelect', "Power up", 2); }
            if (powerState & 1) {
                addOption('d5actionSelect', "Réinitialiser", 10);
                addOption('d5actionSelect', "Cycle de puissance", 5);
                addOption('d5actionSelect', "Éteindre", 8);
            }
            if (amtPowerBootCapabilities['ForceDiagnosticBoot'] == true) {
                if (powerState & 2) { addOption('d5actionSelect', "Mise sous tension du diagnostic", 300); }
                if (powerState & 1) { addOption('d5actionSelect', "Réinitialiser au diagnostic", 301); }
            }
            if ((amtversion > 9) && (powerState & 1)) {
                addOption('d5actionSelect', "Réveil du système d'exploitation en veille", 500);
                addOption('d5actionSelect', "Économie d'énergie du système d'exploitation", 501);
                addOption('d5actionSelect', "Soft-off", 12);
                addOption('d5actionSelect', "Redémarrage en douceur", 14);
                addOption('d5actionSelect', "Dormir", 4);
                addOption('d5actionSelect', "Hiberner", 7);
            }
            if (amtPowerBootCapabilities['BIOSSetup'] == true) {
                if (powerState & 2) { addOption('d5actionSelect', "Mettez le BIOS sous tension", 100); }
                if (powerState & 1) { addOption('d5actionSelect', "Réinitialiser au BIOS", 101); }
            }
            if (amtPowerBootCapabilities['SecureErase'] == true) {
                if (powerState & 2) { addOption('d5actionSelect', "Mise sous tension pour effacement sécurisé", 104); }
                if (powerState & 1) { addOption('d5actionSelect', "Réinitialiser pour effacer sécurisé", 105); }
            }
            if ((amtPowerBootCapabilities['PlatformErase'] != null) && (amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] >= 32768) && (amtsysstate['CIM_BootService'].response['EnabledState'] & 2)) {
                if (powerState & 2) { addOption('d5actionSelect', "Power up to Platform Erase", 106); }
                if (powerState & 1) { addOption('d5actionSelect', "Reset to Platform Erase", 107); }
            }
            // ###BEGIN###{IDER}
            if (powerState & 1) { addOption('d5actionSelect', "Réinitialiser sur la disquette IDE-R", 200); }
            if (powerState & 2) { addOption('d5actionSelect', "Mettez sous tension la disquette IDE-R", 201); }
            if (powerState & 1) { addOption('d5actionSelect', "Réinitialiser sur CD-ROM IDE-R", 202); }
            if (powerState & 2) { addOption('d5actionSelect', "Allumer le CD-ROM IDE-R", 203); }
            // ###END###{IDER}
            if (powerState & 1) { addOption('d5actionSelect', "Réinitialiser à PXE", 400); }
            if (powerState & 2) { addOption('d5actionSelect', "Allumez PXE", 401); }
            // ###BEGIN###{PowerControl-Advanced}
            // ###BEGIN###{PowerControl-OneClick}
            if (amtPowerBootCapabilities['ForceUEFIHTTPSBoot'] === true) {
                if (powerState & 1) { addOption('d5actionSelect', "Reset to HTTPS Boot", 600); }
                if (powerState & 2) { addOption('d5actionSelect', "Power on to HTTPS Boot", 601); }
            }
            // ###END###{PowerControl-OneClick}
            addOption('d5actionSelect', "Action personnalisée ...", 999);
            // ###END###{PowerControl-Advanced}
            if (amtversion > 5) { addOption('d5actionSelect', "Consentement de l'utilisateur ...", 998); } // On AMT 5 and higher, offer the option of doing user consent alone.
            setDialogMode(5, "Actions de puissance", 3, powerActionDlgCheck);
        }

        // ###BEGIN###{PowerControl-Advanced}
        // ###BEGIN###{PowerControl-OneClick}
        function oneClickFileSelect() { QE('idx_dlgOkButton', Q('ocrfile').files.length == 1); }
        // ###END###{PowerControl-OneClick}
        // ###END###{PowerControl-Advanced}

        function powerActionDlgCheck() {
            AmtOcrPba = null;
            AmtOcrPbaLength = 0;
            var action = d5actionSelect.value;

            // ###BEGIN###{PowerControl-Advanced}
            // ###BEGIN###{PowerControl-OneClick}
            if ((action == 600) || (action == 601)) {
                // ###BEGIN###{Mode-NodeWebkit}
                // If the connection to intel AMT is not TLS, warn and exit now.
                if (wsstack.comm.xtlsCertificate == null) { messagebox("Action de puissance", "This feature requires a TLS connection to Intel AMT"); return; }
                // ###END###{Mode-NodeWebkit}
                var x = "Select a disk image for remote boot." + '<br /><br /><input id=ocrfile type=file onchange=oneClickFileSelect() accept=".iso">';
                setDialogMode(11, "HTTPS Boot", 3, function () {
                    var files = Q('ocrfile').files;
                    if (files.length != 1) return;
                    setupWebServer(urlvars['webcn'] ? urlvars['webcn'] : wsstack.comm.localAddress);
                    webserver.setupBootImage(files[0].path, (urlvars['webcn'] ? urlvars['webcn'] : wsstack.comm.localAddress));
                    powerActionDlg();
                }, x);
                QE('idx_dlgOkButton', false);
                return;
            }
            // ###END###{PowerControl-OneClick}
            // ###END###{PowerControl-Advanced}

            if ((action == 500) || (action == 501)) {
                // Perform OS wake from standby or OS sleep (Intel AMT 10+)
                amtstack.RequestOSPowerStateChange((action == 501)?3:2, function (stack, name, response, status) {
                    if (status == 200) { QH('id_dialogMessage', "Action de puissance terminée."); } else { QH('id_dialogMessage', format("Erreur d'action d'alimentation # {0}.", status)); }
                    setDialogMode(1, "Action de puissance", 0);
                    setTimeout(function () { setDialogMode(0); }, 1300);
                });
            } else if ((action == 104) || (action == 105)) {
                var x = ("Confirmer l'exécution d'Intel&reg; Remote Secure Erase?" + '<br>' + "Saisissez le mot de passe d'effacement sécurisé si nécessaire." + '<br>');
                x += ('<br><div style=height:16px><input type=password id=rsepass maxlength=32 style=float:right;width:240px><div>' + "Mot de passe" + '</div></div>');
                x += ('<br><div style=color:red>' + "<b> AVERTISSEMENT: </b> Cela effacera les données sur le système distant." + '</div>');
                // ###BEGIN###{Mode-NodeWebkit}
                if (wsstack.comm.xtlsFingerprint == null) { x += ('<div style=color:red>' + "<b> AVERTISSEMENT: </b> TLS n'est pas utilisé, le mot de passe sera envoyé en clair." + '</div>'); }
                // ###END###{Mode-NodeWebkit}
                rsepass = 1;
                setDialogMode(11, "Actions de puissance", 3, powerActionDlg, x);
            } else if ((action == 106) || (action == 107)) {
                powerActionDlgRPE();
            // ###BEGIN###{PowerControl-OneClick}
            } else if ((action == 999) && (amtversion >= 15)) {
                statusbox("Actions de puissance", "Checking boot sources...");            
                amtstack.BatchEnum('', ['CIM_BootSourceSetting'], powerActionDlgCheck00, true);
            // ###END###{PowerControl-OneClick}
            } else {
                powerActionDlg();
            }
        }
        
        function powerActionDlgRPE(advanced) {
            var x = ("Confirm execution of Intel&reg; Remote Platform Erase?" + '<br>');
            x += ('<br><div style=color:red>' + "<b> AVERTISSEMENT: </b> Cela effacera les données sur le système distant." + '</div>');
            var actionTaken = [], platfromEraseSupport = amtPowerBootCapabilities['PlatformErase'];
            if (platfromEraseSupport & (1 << 1)) { actionTaken.push('<label><input id=rpef1 type=checkbox onchange=powerActionDlgRPEValidate()>' + "Pyrite Revert" + '</label>'); }
            if (platfromEraseSupport & (1 << 2)) { actionTaken.push('<label><input id=rpef2 type=checkbox onchange=powerActionDlgRPEValidate()>' + "Secure Erase All SSDs" + '</label>'); }
            if (platfromEraseSupport & (1 << 3)) { actionTaken.push('<label><input id=rpef3 type=checkbox onchange=powerActionDlgRPEValidate()>' + "Verify Storage Erase" + '</label>'); }
            if (platfromEraseSupport & (1 << 6)) { actionTaken.push('<label><input id=rpef6 type=checkbox onchange=powerActionDlgRPEValidate()>' + "TPM Clear" + '</label>'); }
            if (platfromEraseSupport & (1 << 16)) { actionTaken.push('<label><input id=rpef16 type=checkbox onchange=powerActionDlgRPEValidate()>' + "OEM Custom Action" + '</label>'); }
            if (platfromEraseSupport & (1 << 25)) { actionTaken.push('<label><input id=rpef25 type=checkbox onchange=powerActionDlgRPEValidate()>' + "Clear BIOS NVM Variables" + '</label>'); }
            if (platfromEraseSupport & (1 << 26)) { actionTaken.push('<label><input id=rpef26 type=checkbox onchange=powerActionDlgRPEValidate()>' + "BIOS Reload of Golden Configuration" + '</label>'); }
            if (platfromEraseSupport & (1 << 31)) { actionTaken.push('<label><input id=rpef31 type=checkbox onchange=powerActionDlgRPEValidate()>' + "CSME Unconfigure" + '</label>'); }
            if (actionTaken.length > 0) { x += (format('<br />' + "Select the actions to take:" + '<br /><br /><div style=margin-left:16px>{0}</div><br />', actionTaken.join('<br />'))); }
            x += '<div id=rpepsid style=margin-top:4px;margin-bottom:4px;display:none>' + addHtmlValue("Pyrite PSID", '<input id=rpepsidx style=width:210px maxlength=64 type=input>') + '</div>';
            x += '<div id=rpessdpass style=margin-top:4px;margin-bottom:4px;display:none>' + addHtmlValue("SSD Master Password", '<input id=rpessdpassx style=width:210px maxlength=64 type=input>') + '</div>';
            x += '<div id=rpeeomdata style=margin-top:4px;margin-bottom:4px;display:none>' + addHtmlValue("OEM Data (HEX)", '<input id=rpeoemdatax style=width:210px maxlength=256 type=input>') + '</div>';
            setDialogMode(11, "Actions de puissance", 3, powerActionDlgRPEEx, x, advanced);
            QE('idx_dlgOkButton', false);
        }

        function powerActionDlgRPEValidate() {
            var rpeFlags = 0, platfromEraseSupport = amtPowerBootCapabilities['PlatformErase'], sf = [1, 2, 3, 6, 16, 25, 26, 31];
            for (var i in sf) { if (platfromEraseSupport & (1 << sf[i])) { if (Q('rpef' + sf[i]).checked) { rpeFlags += (1 << sf[i]); } } }
            QV('rpessdpass', rpeFlags & 4);
            QV('rpeeomdata', rpeFlags & (1 << 16));
            QE('idx_dlgOkButton', rpeFlags);
        }

        var platfromEraseTLV = null;
        function powerActionDlgRPEEx(b, advanced) {
            var rpeFlags = 0, platfromEraseSupport = amtPowerBootCapabilities['PlatformErase'], sf = [1, 2, 3, 6, 16, 25, 26, 31];
            for (var i in sf) { if (platfromEraseSupport & (1 << sf[i])) { if (Q('rpef' + sf[i]).checked) { rpeFlags += (1 << sf[i]); } } }
            var tlv = makeUefiBootParam(1, rpeFlags, 4), tlvlen = 1;
            if (rpeFlags & 2) { tlv += makeUefiBootParam(10, Q('rpepsidx').value); tlvlen++; }
            if (rpeFlags & 4) { tlv += makeUefiBootParam(20, Q('rpessdpassx').value); tlvlen++; }
            if ((rpeFlags & (1 << 16)) && (Q('rpeoemdatax').value != '')) { tlv += makeUefiBootParam(20, hex2rstr(Q('rpeoemdatax').value), null, 11); tlvlen++; }
            platfromEraseTLV = { tlv: btoa(tlv), tlvlen: tlvlen };
            if (advanced) {
                // Attempt user consent
                statusbox("Action de puissance", "Vérification de l'état ...");
                amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1);
            } else {
                powerActionDlg();
            }
        }

        // ###BEGIN###{PowerControl-OneClick}
        var AmtOcrPba = null;
        var AmtOcrPbaLength = 0;
        function powerActionDlgCheck00(stack, name, response, status) {
            if (status != 200) { messagebox("Action de puissance", format("GET CIM_BootSourceSetting, Error #{0}", status) + ((response.Header && response.Header.WsmanError) ? (', ' + response.Header.WsmanError) : '')); return; }
            var bootSources = response.CIM_BootSourceSetting.responses;
            AmtOcrPba = {};
            for (var i = 0; i < bootSources.length; i++) {
                var instanceid = bootSources[i]['InstanceID'];
                if ((instanceid != null) && instanceid.toString().startsWith('Intel(r) AMT: Force OCR UEFI Boot')) {
                    try {
                        var arr = instanceid.trim().split(' ');
                        idx = parseInt(arr[arr.length - 1]);
                        AmtOcrPba[parseInt(idx)] = { instance: bootSources[i]['BIOSBootString'], bootstr: bootSources[i]['BootString'] };
                        AmtOcrPbaLength++;
                    } catch (e) { }
                }
            }
            powerActionDlg();
        }
        // ###END###{PowerControl-OneClick}

        function powerActionDlg() {
            //if (amtversion == 0) return;
            //if (amtversion > 6) { amtstack.Get('IPS_OptInService', powerActionResponse0); } else { amtstack.Get('AMT_BootSettingData', powerActionResponse1); }
            var action = d5actionSelect.value;
            // ###BEGIN###{PowerControl-Advanced}
            if (action == 999) { showAdvPowerDlg(); return; }
            // ###END###{PowerControl-Advanced}
            if (action == 998) { amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1); return; }

            // Some actions will not work if KVM/SOL/IDER are connected. If we perform these, disconnect now.
            if ((action < 10) && (action > 2) && (urlvars['noredirdisconnect'] == null)) {
                // ###BEGIN###{Desktop}
                if (desktop.State == 3) connectDesktop();
                // ###END###{Desktop}
                // ###BEGIN###{Terminal}
                if (terminal.State == 3) connectTerminal();
                // ###END###{Terminal}
                // ###BEGIN###{IDER}
                if ((ider != undefined) && (ider.state == 3)) iderStop();
                // ###END###{IDER}
            }

            statusbox("Action de puissance", "Vérification de l'état ...");
            if ((rsepass != null) && (rsepass === 1)) { rsepass = Q('rsepass').value; }

            var uc = true; // Check if we need to ask for user consent
            if (amtversion < 6) uc = false; // Below AMT 6, user consent does not exist.
            if ((currentView == 13) && (action == 8)) uc = false; // if in terminal, don't ask for it if power down.
            if ((currentView != 13) && (action <= 10)) uc = false; // if not in terminal, don't ask for basic operations.

            if (uc) {
                // Attempt user consent
                amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1);
            } else {
                // Skip user consent
                amtstack.Get('AMT_BootSettingData', powerActionResponse1, 0, 1);
            }
        }

        // ###BEGIN###{PowerControl-Advanced}
        var AvdPowerDlg;
        function showAdvPowerDlg() {
            try { Q('idx_d24Command').value = (amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] == 2)?10:2; } catch (ex) { }

            // Available force boot options
            var forceBootDeviceOptions = '<option value=0>None</option><option id="ForceDVDBootOption" value=1>Force CD/DVD Boot</option><option id="ForcePXEBootOption" value=2>Force PXE Boot</option><option id="ForceHDBootOption" value=3>Force Hard Disk Boot</option><option id="ForceDiagBootOption" value=4>Force Diagnostic Boot</option>';

            // Show boot capabilities
            QV('d24dBiosPause', amtPowerBootCapabilities['BIOSPause'] == true);
            QV('d24dBiosSecureBoot', amtPowerBootCapabilities['BIOSSecureBoot'] == true);
            QV('d24dReflashBios', amtPowerBootCapabilities['BIOSReflash'] == true);
            QV('d24dBiosSetup', amtPowerBootCapabilities['BIOSSetup'] == true);
            QV('ForceDVDBootOption', amtPowerBootCapabilities['ForceCDorDVDBoot'] == true);
            QV('ForceDiagBootOption', amtPowerBootCapabilities['ForceDiagnosticBoot'] == true);
            QV('ForceHDBootOption', amtPowerBootCapabilities['ForceHardDriveBoot'] == true);
            //QV('', amtPowerBootCapabilities['ForceHardDriveSafeModeBoot'] == true);
            //QV('', amtPowerBootCapabilities['ForceWinREBoot'] == true);
            QV('ForcePXEBootOption', amtPowerBootCapabilities['ForcePXEBoot'] == true);
            // ###BEGIN###{PowerControl-OneClick}
            if ((AmtOcrPbaLength > 0) && (amtPowerBootCapabilities['ForceUEFIPBABoot'] == true)) {
                forceBootDeviceOptions += '<option id="ForceUEFIBootOption" value=5>Force OCR UEFI Boot Option</option>';
                var x = '';
                for (var i in AmtOcrPba) { x += '<option value=' + i + '>' + AmtOcrPba[i].instance + '</option>'; }
                QH('idx_d24customBootMediaIndex', x);
            }
            var httpsBootPossible = ((meshCentralServer == null) && (wsstack.comm.xtlsCertificate != null)) || (meshCentralServer!=null && ((currentcomputer.conn & 4) == 4) &&  currentcomputer.tls == 1) || (meshCentralServer!=null && ((currentcomputer.conn & 2) == 2) )
            if ((amtPowerBootCapabilities['ForceUEFIHTTPSBoot'] == true) && httpsBootPossible) { forceBootDeviceOptions += '<option id="ForceHttpBootOption" value=6>Force OCR UEFI HTTPS Boot (.iso)</option>'; }
            if ((amtPowerBootCapabilities['ForceUEFIHTTPSBoot'] == true) && httpsBootPossible) { forceBootDeviceOptions += '<option id="ForceHttpUrlBootOption" value=7>Force OCR UEFI HTTPS Boot (url)</option>'; }
            // ###END###{PowerControl-OneClick}
            QV('d24dForceProgressEvents', amtPowerBootCapabilities['ForcedProgressEvents'] == true);
            QV('d24dUseIDER', amtPowerBootCapabilities['IDER'] == true);
            QV('d24dLockKeyboard', amtPowerBootCapabilities['KeyboardLock'] == true);
            QV('d24dLockPowerButton', amtPowerBootCapabilities['PowerButtonLock'] == true);
            QV('d24dLockResetButton', amtPowerBootCapabilities['ResetButtonLock'] == true);
            QV('d24dSerialOverLan', amtPowerBootCapabilities['SOL'] == true);
            QV('d24dSecureErase', amtPowerBootCapabilities['SecureErase'] == true);
            QV('d24dPlatformErase', (amtPowerBootCapabilities['PlatformErase'] != null) && (amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] >= 32768) && ((amtsysstate['CIM_BootService'].response['EnabledState'] & 2) != 0));
            QV('d24dFirmwareReset', amtPowerBootCapabilities['ConfigurationDataReset'] == true);
            QV('d24dLockSleepButton', amtPowerBootCapabilities['SleepButtonLock'] == true);
            QV('d24dUserPasswordBypass', amtPowerBootCapabilities['UserPasswordBypass'] == true);
            QV('idx_d24Verbocity1', amtPowerBootCapabilities['VerbosityQuiet'] == true);
            QV('idx_d24Verbocity2', amtPowerBootCapabilities['VerbosityVerbose'] == true);
            QV('idx_d24Verbocity3', amtPowerBootCapabilities['VerbosityScreenBlank'] == true);
            QV('d24p500', amtversion > 9);
            QV('d24p501', amtversion > 9);

            QH('idx_d24ForceBootDevice', forceBootDeviceOptions);
            setDialogMode(24, "Action de puissance personnalisée", 3, showAdvPowerDlgOk);
            showAdvPowerDlgChange();
        }

        function showAdvPowerDlgChange() {
            var ok = true;
            QV('idd_d24IDERBootDevice', Q('d24UseIDER').checked);
            QV('idd_d24RSEPass', Q('d24SecureErase') ? Q('d24SecureErase').checked : false);
            // ###BEGIN###{Mode-NodeWebkit}
            QV('idd_d24RSEPassTlsWarn', (wsstack.comm.xtlsFingerprint == null) && (Q('d24SecureErase') ? Q('d24SecureErase').checked : false));
            // ###END###{Mode-NodeWebkit}

            // If this is a OS power state change, gray out all of the options.
            var ospower = ((Q('idx_d24Command').value >= 500) && (Q('idx_d24Command').value < 600));
            QE('idx_d24ForceBootDevice', !ospower);
            QE('idx_d24BootMediaIndex', !ospower);
            QE('idd_d24IDERBootDevice', !ospower);
            QE('idx_d24Verbocity', !ospower);
            QE('idd_d24RSEPass', !ospower);

            // If the boot source is not "None" (0), disable all boot settings.
            //var bootSettingOpts = ['d24BiosPause', 'd24BiosSecureBoot', 'd24BiosSetup', 'd24ForceProgressEvents', 'd24LockPowerButton', 'd24LockResetButton', 'd24LockSleepButton', 'd24LockKeyboard', 'd24UserPasswordBypass', 'd24ReflashBios', 'd24SafeMode', 'd24UseIDER', 'd24SerialOverLan', 'd24SecureErase'];
            //if ((idx_d24ForceBootDevice.value > 0) && (idx_d24ForceBootDevice.value < 5)) { for (var i in bootSettingOpts) { Q(bootSettingOpts[i]).checked = false; } }
            //for (var i in bootSettingOpts) { QE(bootSettingOpts[i], idx_d24ForceBootDevice.value == 0); }

            // ###BEGIN###{PowerControl-OneClick}
            var bootSourceIndex = Q('idx_d24ForceBootDevice').value;
            QV('idx_d24bootSource', bootSourceIndex < 5);
            QV('idx_d24customBootSource', bootSourceIndex == 5)
            QV('idx_d24diskImage', bootSourceIndex == 6);
            QV('idx_d24diskImageUrl', bootSourceIndex == 7);
            QV('idx_d24diskImageHttpTimeout', (bootSourceIndex == 7) && (amtversion > 16));
            if ((bootSourceIndex == 6) && (Q('idx_d24ocrBootFile').files.length != 1)) { ok = false; }
            if ((bootSourceIndex == 7) && (Q('idx_d24ocrBootUrl').value.trim().toLowerCase().startsWith('https://') == false)) { ok = false; }
            if ((bootSourceIndex == 7) && (amtversion > 16)) {
                var timeout = parseInt(Q('idx_d24ocrBootHttpBootTimeout').value);
                if (isNaN(timeout) || (timeout > 65535) || (timeout < 0)) { ok = false; }
            }
            // ###END###{PowerControl-OneClick}

            QE('idx_dlgOkButton', ok);
        }

        function showAdvPowerDlgOk() {
            // ###BEGIN###{PowerControl-OneClick}
            var forceBootSelection = Q('idx_d24ForceBootDevice').value;
            // ###BEGIN###{Mode-NodeWebkit}            
            if (((forceBootSelection == 5) || (forceBootSelection == 6) || (forceBootSelection == 7)) && 
                (((meshCentralServer == null) && (wsstack.comm.xtlsCertificate == null)) || (meshCentralServer!=null && ((currentcomputer.conn & 4) == 4) &&  currentcomputer.tls == 0))) {
                messagebox("Action de puissance", "This feature requires a TLS connection to Intel AMT"); return;
            }
            // ###END###{Mode-NodeWebkit}
            if (forceBootSelection == 6) {
                var files = Q('idx_d24ocrBootFile').files;
                if (files.length == 1) {
                    setupWebServer(urlvars['webcn'] ? urlvars['webcn'] : wsstack.comm.localAddress);
                    webserver.setupBootImage(files[0].path, (urlvars['webcn'] ? urlvars['webcn'] : wsstack.comm.localAddress));
                }
            }
            // ###END###{PowerControl-OneClick}

            var action = Q('idx_d24Command').value;
            if ((action == 500) || (action == 501)) {
                // Perform OS wake from standby or OS sleep (Intel AMT 10+)
                amtstack.RequestOSPowerStateChange((action == 501) ? 3 : 2, function (stack, name, response, status) {
                    if (status == 200) { QH('id_dialogMessage', "Action de puissance terminée."); } else { QH('id_dialogMessage', format("Erreur d'action d'alimentation # {0}.", status)); }
                    setDialogMode(1, "Action de puissance", 0);
                    setTimeout(function () { setDialogMode(0); }, 1300);
                });
            } else {
                // Fetch all of the user data
                AvdPowerDlg = {};
                AvdPowerDlg.Action = Q('idx_d24Command').value;
                AvdPowerDlg.BIOSPause = Q('d24BiosPause').checked;
                AvdPowerDlg.BIOSSecureBoot = Q('d24BiosSecureBoot').checked;
                AvdPowerDlg.BIOSSetup = Q('d24BiosSetup').checked;
                AvdPowerDlg.BootMediaIndex = Q('idx_d24BootMediaIndex').value;
                AvdPowerDlg.FirmwareVerbosity = Q('idx_d24Verbocity').value;
                AvdPowerDlg.ForcedProgressEvents = Q('d24ForceProgressEvents').checked;
                AvdPowerDlg.IDERBootDevice = Q('idx_d24IDERBootDevice').value; // 0 = Boot on Floppy, 1 = Boot on IDER
                AvdPowerDlg.LockKeyboard = Q('d24LockKeyboard').checked;
                AvdPowerDlg.LockPowerButton = Q('d24LockPowerButton').checked;
                AvdPowerDlg.LockResetButton = Q('d24LockResetButton').checked;
                AvdPowerDlg.LockSleepButton = Q('d24LockSleepButton').checked;
                AvdPowerDlg.ReflashBIOS = Q('d24ReflashBios').checked;
                AvdPowerDlg.UseIDER = Q('d24UseIDER').checked;
                AvdPowerDlg.UseSOL = Q('d24SerialOverLan').checked;
                AvdPowerDlg.UseSafeMode = Q('d24SafeMode').checked;
                AvdPowerDlg.UserPasswordBypass = Q('d24UserPasswordBypass').checked;
                AvdPowerDlg.SecureErase = Q('d24SecureErase').checked;
                AvdPowerDlg.PlatformErase = Q('d24PlatformErase').checked
                AvdPowerDlg.FirmwareReset = Q('d24FirmwareReset').checked;
                if ((AvdPowerDlg.SecureErase === true) && (Q('d24rsepass').value.length > 0)) { AvdPowerDlg.RSEPassword = Q('d24rsepass').value; }

                if (AvdPowerDlg.PlatformErase === true) {
                    // Ask additional information about RPE
                    powerActionDlgRPE(true);
                } else {
                    // Attempt user consent
                    statusbox("Action de puissance", "Vérification de l'état ...");
                    amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1);
                }
            }
        }
        // ###END###{PowerControl-Advanced}

        function powerActionResponse0(stack, name, response, status) {
            //if (errcheck(status, stack)) return; // TODO: If AMT 5 or below, this will error and we need to skip user consent.
            if (status != 200) {
                if (connectDesktopConsent) { connectDesktop(true); } else { messagebox("Action de puissance", format("Erreur # {0}", status)); }
                return;
            }
            //console.log('powerActionResponse0(' + name + ',' + ObjectToString2(response) + ',' + status + ')');
            //console.log("OptInRequired:", response.Body['OptInRequired']);
            //console.log("OptInState:", response.Body['OptInState']);
            //console.log(response);
            if (((response.Body['OptInRequired'] == 0xFFFFFFFF) || (connectDesktopConsent && (response.Body['OptInRequired'] != 0))) && (response.Body['OptInState'] != 3) && (response.Body['OptInState'] != 4)) {
                if (response.Body['OptInState'] == 2) {
                    amtstack.IPS_OptInService_CancelOptIn(null);
                    d6ConsentText.value = ''; // Reset user consent code to empty
                    setDialogMode(6, "Consentement de l'utilisateur", 11, powerActionSendConsent);
                    checkConsentDisplay();
                    consentChanged();
                    return;
                }
                //console.log("Opt-in Required.", response.Body['OptInRequired']);
                statusbox("Action de puissance", "Démarrage de l'opt-in ...");
                amtstack.IPS_OptInService_StartOptIn(powerActionResponseC1, 0, 1);
            } else {
                if (connectDesktopConsent) { setDialogMode(0); connectDesktop(true); return; }
                if (d5actionSelect.value == 998) { messagebox("Consentement de l'utilisateur", "Le consentement de l'utilisateur n'est pas nécessaire."); return; }
                statusbox("Action de puissance", "Obtention des paramètres de démarrage ...");
                amtstack.Get('AMT_BootSettingData', powerActionResponse1, 0, 1);
            }
        }

        function powerActionResponseC1(stack, name, response, status) {
            //if (errcheck(status, stack)) return;
            //console.log('powerActionResponseC1', name, status, response);
            if (status != 200) { if (connectDesktopConsent) { setDialogMode(0); connectDesktop(true); } else { messagebox("Action de puissance", format("Erreur #", status)); } return; }
            //console.log("powerActionResponseC1(" + name + "," + ObjectToString2(response) + "," + status + ")");
            if (response.Body['ReturnValue'] != 0) {
                if (connectDesktopConsent) { setDialogMode(0); connectDesktop(true); } else { messagebox("Erreur de consentement de l'utilisateur", response.Body.ReturnValueStr.replace(/_/g, ' ')); }
            } else {
                d6ConsentText.value = ''; // Reset user consent code to empty
                setDialogMode(6, "Consentement de l'utilisateur", 11, powerActionSendConsent);
                checkConsentDisplay();
                consentChanged();

                // Check if the machine is powered down, if it is, power it up for user consent.
                amtstack.Enum('CIM_ServiceAvailableToElement', function(stack, name, responses, status) {
                    if (errcheck(status, stack)) return;
                    amtsysstate['CIM_ServiceAvailableToElement'].responses = responses;
                    updateSystemStatus();
                    if ((amtsysstate['CIM_ServiceAvailableToElement'] != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses != null) && (amtsysstate['CIM_ServiceAvailableToElement'].responses.length > 0)) {
                        if (amtsysstate['CIM_ServiceAvailableToElement'].responses[0]['PowerState'] != 2) {
                            // System is not on, power it on now.
                            amtstack.RequestPowerStateChange(2, function (stack, name, response, status) { });
                        }
                    }
                });
            }
        }

        //function powerActionCancelConsent() { amtstack.IPS_OptInService_CancelOptIn(null); }

        function powerActionSendConsent(buttons) {
            console.log('powerActionSendConsent', buttons);
            if (buttons == 0) {
                // Cancel button
                amtstack.IPS_OptInService_CancelOptIn(function () { });
                connectDesktopConsent = false;
                desktop.Stop();
            } else {
                // OK Button
                statusbox("Action de puissance", "Envoi du consentement de l'utilisateur ...");
                amtstack.IPS_OptInService_SendOptInCode(d6ConsentText.value, powerActionResponseC2, 0, 1);
            }
        }

        function powerActionResponseC2(stack, name, response, status) {
            //if (errcheck(status, stack)) return;
            if (status != 200) { messagebox("Action de puissance", format("Erreur # {0}", status)); return; }
            //console.log("powerActionResponseC2(" + name + "," + ObjectToString2(response) + "," + status + ")");
            if (response.Body['ReturnValue'] != 0) {
                amtstack.Get('IPS_OptInService', powerActionResponse0, 0, 1);
            } else {
                if (connectDesktopConsent) { setDialogMode(0); connectDesktop(true); return; }
                if (d5actionSelect.value == 998) { messagebox("Consentement de l'utilisateur", "Le consentement de l'utilisateur a réussi."); return; } // This was just a user consent request, no need to go further.
                statusbox("Action de puissance", "Vérification de l'état ...");
                amtstack.Get('AMT_BootSettingData', powerActionResponse1, 0, 1);
            }
        }

        function powerActionResponse1(stack, name, response, status) {
            //if (errcheck(status, stack)) return;
            if (status != 200) { messagebox("Action de puissance", format("Erreur # {0}", status)); return; }
            //console.log("powerActionResponse1(" + name + "," + ObjectToString2(response) + "," + status + ")");
            var action = d5actionSelect.value;
            var r = response.Body;
            r['ConfigurationDataReset'] = false;

            // Clean up parameters
            delete r['WinREBootEnabled'];
            delete r['UEFILocalPBABootEnabled'];
            delete r['UEFIHTTPSBootEnabled'];
            delete r['SecureBootControlEnabled'];
            delete r['BootguardStatus'];
            delete r['OptionsCleared'];
            delete r['BIOSLastStatus'];
            delete r['UefiBootParametersArray'];
            delete r['RPEEnabled'];

            // ###BEGIN###{PowerControl-Advanced}
            if (action == 999) {
                r['BIOSPause'] = AvdPowerDlg.BIOSPause;
                r['EnforceSecureBoot'] = AvdPowerDlg.BIOSSecureBoot;
                r['BIOSSetup'] = AvdPowerDlg.BIOSSetup;
                r['BootMediaIndex'] = AvdPowerDlg.BootMediaIndex;
                r['FirmwareVerbosity'] = AvdPowerDlg.FirmwareVerbosity;
                r['ForcedProgressEvents'] = AvdPowerDlg.ForcedProgressEvents;
                r['IDERBootDevice'] = AvdPowerDlg.IDERBootDevice; // 0 = Boot on Floppy, 1 = Boot on IDER
                r['LockKeyboard'] = AvdPowerDlg.LockKeyboard;
                r['LockPowerButton'] = AvdPowerDlg.LockPowerButton;
                r['LockResetButton'] = AvdPowerDlg.LockResetButton;
                r['LockSleepButton'] = AvdPowerDlg.LockSleepButton;
                r['ReflashBIOS'] = AvdPowerDlg.ReflashBIOS;
                r['UseIDER'] = AvdPowerDlg.UseIDER;
                r['UseSOL'] = AvdPowerDlg.UseSOL;
                r['UseSafeMode'] = AvdPowerDlg.UseSafeMode;
                r['UserPasswordBypass'] = AvdPowerDlg.UserPasswordBypass;
                if (r['SecureErase'] != null) {
                    r['SecureErase'] = ((AvdPowerDlg.SecureErase) && (amtPowerBootCapabilities['SecureErase'] == true));
                    if ((r['SecureErase'] == true) && (AvdPowerDlg.RSEPassword)) { r['RSEPassword'] = AvdPowerDlg.RSEPassword; }
                }
                if (r['PlatformErase'] != null) {
                    if ((amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] >= 32768) && (amtsysstate['CIM_BootService'].response['EnabledState'] & 2) && ((AvdPowerDlg.PlatformErase) && (amtPowerBootCapabilities['PlatformErase'] != null) && ((amtPowerBootCapabilities['PlatformErase'] & 1) != 0))) {
                        r['PlatformErase'] = true;
                        r['UefiBootParametersArray'] = platfromEraseTLV.tlv;
                        r['UefiBootNumberOfParams'] = platfromEraseTLV.tlvlen;
                    } else {
                        r['PlatformErase'] = false;
                    }
                }
                if (r['ConfigurationDataReset'] != null) { r['ConfigurationDataReset'] = AvdPowerDlg.FirmwareReset; }
            } else {
                // ###END###{PowerControl-Advanced}
                r['BIOSPause'] = false;
                r['EnforceSecureBoot'] = false;
                r['BIOSSetup'] = (action > 99 && action < 104);
                r['BootMediaIndex'] = 0;
                r['FirmwareVerbosity'] = 0;
                r['ForcedProgressEvents'] = false;
                r['IDERBootDevice'] = ((action == 202) || (action == 203))?1:0; // 0 = Boot on Floppy, 1 = Boot on IDER
                r['LockKeyboard'] = false;
                r['LockPowerButton'] = false;
                r['LockResetButton'] = false;
                r['LockSleepButton'] = false;
                r['ReflashBIOS'] = false;
                r['UseIDER'] = ((action > 199) && (action < 300));
                //r['UseSOL'] = ((currentView == 13) && (action != 8) && (action != 300) && (action != 301)); // If we are looking at the terminal, turn on SOL. SOL can't be used with diagnostic mode (300/301)
                r['UseSOL'] = ((currentView == 13) && (action != 8) && (action < 300)); // If we are looking at the terminal, turn on SOL.
                r['UseSafeMode'] = false;
                r['UserPasswordBypass'] = false;
                if (r['SecureErase'] != null) {
                    r['SecureErase'] = (((action == 104) || (action == 105)) && (amtPowerBootCapabilities['SecureErase'] == true));
                    if ((r['SecureErase'] === true) && (rsepass.length > 0)) { r['RSEPassword'] = rsepass; }
                }
                if (r['PlatformErase'] != null) {
                    if ((amtsysstate['CIM_BootService'] != null) && (amtsysstate['CIM_BootService'].response['EnabledState'] >= 32768) && (amtsysstate['CIM_BootService'].response['EnabledState'] & 2) && (((action == 106) || (action == 107)) && (amtPowerBootCapabilities['PlatformErase'] != null) && (((amtPowerBootCapabilities['PlatformErase'] & 1)) != 0))) {
                        r['PlatformErase'] = true;
                        r['UefiBootParametersArray'] = platfromEraseTLV.tlv;
                        r['UefiBootNumberOfParams'] = platfromEraseTLV.tlvlen;
                    } else {
                        r['PlatformErase'] = false;
                    }
                }
                if (r['ConfigurationDataReset'] != null) { r['ConfigurationDataReset'] = false; }
                rsepass = null;
                // ###BEGIN###{PowerControl-Advanced}
            }

            // ###BEGIN###{PowerControl-OneClick}
            // Add OCR TLV parameters if firmware supports OCR and Force HTTPS Boot is requested
            if ((action == 999) && (Q('idx_d24ForceBootDevice').value == 7)) { // Force UEFI HTTPS Boot using URL
                const bootUrl = new URL(Q('idx_d24ocrBootUrl').value.trim());
                const bootUrlUsername = bootUrl.username;
                const bootUrlPassword = bootUrl.password;
                bootUrl.username = bootUrl.password = '';
                var uefiParams = makeUefiBootParam(1, bootUrl.href) + makeUefiBootParam(20, 1, 1) + makeUefiBootParam(30, 0, 2);
                if (bootUrlUsername != '') { uefiParams += makeUefiBootParam(40, bootUrlUsername); } // HTTP basic auth username
                if (bootUrlPassword != '') { uefiParams += makeUefiBootParam(41, bootUrlPassword); } // HTTP basic auth password
                if (amtversion > 16) {
                    var timeout = parseInt(Q('idx_d24ocrBootHttpBootTimeout').value);
                    if (timeout > 0) { uefiParams += makeUefiBootParam(30, timeout, 2); }
                }
                r['UefiBootParametersArray'] = btoa(uefiParams);
                r['UefiBootNumberOfParams'] = 3;
                r['BootMediaIndex'] = 0; // Do not use boot media index for One Click Recovery (OCR)
            } else if ((action == 600) || (action == 601) || ((action == 999) && (Q('idx_d24ForceBootDevice').value == 6))) { // Force UEFI HTTPS Boot
                // Check if using built-in webserver or external webserver
                r['UefiBootParametersArray'] = webserver.lastBootImageArgs.args;
                r['UefiBootNumberOfParams'] = webserver.lastBootImageArgs.argscount;
                r['BootMediaIndex'] = 0; // Do not use boot media index for One Click Recovery (OCR)
            } else if ((action == 999) && (Q('idx_d24ForceBootDevice').value == 5)) {
                var bootstr = AmtOcrPba[Q('idx_d24customBootMediaIndex').value].bootstr;
                console.log('OCR BootStr: ' + bootstr);
                r['UefiBootParametersArray'] = btoa(makeUefiBootParam(2, bootstr) + makeUefiBootParam(3, bootstr.length, 2)); // EFI_DEVICE_PATH (2) + EFI_DEVICE_PATH-LENGTH (3)
                r['UefiBootNumberOfParams'] = 2;
                r['BootMediaIndex'] = 0; // Do not use boot media index for One Click Recovery (OCR)
            }
            // ###END###{PowerControl-OneClick}
            // ###END###{PowerControl-Advanced}

            //if (((action == 104) || (action == 105)) && !r['SecureErase']) { /*console.log("This Intel&reg; AMT does not support Secure Erase");*/ cleanup(); return; }
            console.log("Action de démarrage: " + action);
            console.log("Définition des paramètres de démarrage: " + ObjectToString2(r));
            statusbox("Action de puissance", "Définition des paramètres de démarrage ...");

            // Set the boot order to null, this is needed for some AMT versions that don't clear this automatically.
            amtstack.CIM_BootConfigSetting_ChangeBootOrder(null, function (stack, name, response, status) {
                if (status != 200) { messagebox("Action de puissance", format("PUT CIM_BootConfigSetting_ChangeBootOrder, Error #{0}", status) + ((response.Header && response.Header.WsmanError) ? (', ' + response.Header.WsmanError) : '')); return; }
                if (response.Body['ReturnValue'] != 0) { messagebox("Change Boot Order", "(1) Change Boot Order returns "+ response.Body.ReturnValueStr); return; }
                amtstack.Put('AMT_BootSettingData', r, powerActionResponse2, 0, 1);
            }, 0, 1);
        }

        function powerActionResponse2(stack, name, response, status, tag) {
            //console.log("powerActionResponse2(" + name + "," + response + "," + status + ")");
            if (status != 200) { messagebox("Action de puissance", format("PUT AMT_BootSettingData, erreur # {0}", status) + ((response.Header && response.Header.WsmanError) ? (', ' + response.Header.WsmanError) : '')); return; }
            //if (status == 408) { messagebox("Power Action", "Access denied."); return; }
            //if (errcheck(status, stack)) return;
            //console.log("Setup next boot...");
            statusbox("Action de puissance", "Configuration du prochain démarrage ...");
            amtstack.SetBootConfigRole(1, powerActionResponse3x, 0, 1);
        }

        function powerActionResponse3x(stack, name, response, status) {
            //console.log("powerActionResponse3x(" + name + "," + response + "," + status + ")");
            var action = d5actionSelect.value, bootSource = null;
            // ###BEGIN###{PowerControl-Advanced}
            if (action == 999) {
                // ###BEGIN###{!PowerControl-OneClick}
                if (idx_d24ForceBootDevice.value > 0) { bootSource = ['Force CD/DVD Boot', 'Force PXE Boot', 'Force Hard-drive Boot', 'Force Diagnostic Boot'][idx_d24ForceBootDevice.value - 1]; }
                // ###END###{!PowerControl-OneClick}
                // ###BEGIN###{PowerControl-OneClick}
                if (idx_d24ForceBootDevice.value > 0) { bootSource = ['Force CD/DVD Boot', 'Force PXE Boot', 'Force Hard-drive Boot', 'Force Diagnostic Boot', 'Force OCR UEFI Boot Option ' + Q('idx_d24customBootMediaIndex').value, 'Force OCR UEFI HTTPS Boot', 'Force OCR UEFI HTTPS Boot'][idx_d24ForceBootDevice.value - 1]; }
                // ###END###{PowerControl-OneClick}
            } else {
            // ###END###{PowerControl-Advanced}
                if (action == 300 || action == 301) { bootSource = 'Force Diagnostic Boot'; }
                if (action == 400 || action == 401) { bootSource = 'Force PXE Boot'; }
            // ###BEGIN###{PowerControl-Advanced}
                if (action == 600 || action == 601) { bootSource = 'Force OCR UEFI HTTPS Boot'; }
            }

            // Resetting Force boot data in case it was changed so that it won't be used on the next power action
            Q('idx_d24ForceBootDevice').value = 0;

            // ###END###{PowerControl-Advanced}
            console.log('ChangeBootOrder: ' + bootSource);
            amtstack.CIM_BootConfigSetting_ChangeBootOrder((bootSource == null)?bootSource:'<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_BootSourceSetting</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">Intel(r) AMT: ' + bootSource + '</Selector></SelectorSet></ReferenceParameters>', powerActionResponse3);
        }

        var targetPowerAction = 0;
        function powerActionResponse3(stack, name, response, status) {
            //console.log('powerActionResponse3(' + name + ',' + response + ',' + status + ')');
            if (errcheck(status, stack)) return;
            if (response.Body['ReturnValue'] != 0) { messagebox("Change Boot Order", "(2) Change Boot Order returns "+ response.Body.ReturnValueStr); return; }

            //console.log("Performing Power State Change...");
            statusbox("Action de puissance", "Exécution d'une action de puissance ...");
            var action = d5actionSelect.value;
            if (action == 100 || action == 201 || action == 203 || action == 300 || action == 401 || action == 601) action = 2; // Power up
            if (action == 101 || action == 200 || action == 202 || action == 301 || action == 400 || action == 600) action = 10; // Reset
            if (action == 104) action = 2; // Power on with Remote Secure Erase
            if (action == 105) action = 10; // Reset with Remote Secure Erase
            if (action == 106) action = 2; // Power on with Remote Platfrom Erase
            if (action == 107) action = 10; // Reset with Remote Platfrom Erase
            // ###BEGIN###{PowerControl-Advanced}
            if (action == 999) action = AvdPowerDlg.Action;
            targetPowerAction = action;
            //console.log('RequestPowerStateChange:' + action);
            if (action == 11) { action = 10; }
            if (action < 999) { console.log('RequestPowerStateChange(' + action + ')'); amtstack.RequestPowerStateChange(action, powerActionResponse4); } else { messagebox("Action de puissance", "Jeu d'actions de démarrage suivant."); }
            // ###END###{PowerControl-Advanced}
            // ###BEGIN###{!PowerControl-Advanced}
            targetPowerAction = action;
            amtstack.RequestPowerStateChange(action, powerActionResponse4);
            // ###END###{!PowerControl-Advanced}
        }

        function powerActionResponse4(stack, name, response, status) {
            //console.log("powerActionResponse4(" + name + "," + response + "," + status + ")");
            if (status == 200) {
                // Done!
                //console.log("Action Completed.");
                QH('id_dialogMessage', "Action de puissance terminée.");
                setDialogMode(1, "Action de puissance", 0);
                setTimeout(function() { setDialogMode(0); }, 1300);
            }
            // console.log("Power State Error: " + status);
            // Sometimes Intel AMT with not respond and this will timeout. Try to pull the power state
            amtstack.Get('CIM_AssociatedPowerManagementService', powerActionResponse5, 0, 1);
        }

        function powerActionResponse5(stack, name, response, status) {
            //console.log("powerActionResponse5(" + name + "," + response + "," + status + ")");
            /*
            if (errcheck(status, stack)) return;
            var powerstate = parseInt(response.Body['PowerState']);
            console.log("powerstate: " + powerstate);
            if (targetPowerAction == powerstate) {
                console.log("Action Completed. ");
            } else {
                console.log("Power State Error: " + status + ", CurrentState=" + powerstate + ", TargetState=" + targetPowerAction);
            }
            */
        }

        function consentChanged() { QE('idx_dlgOkButton', d6ConsentText.value.length == 6); }
        function changeConsentDisplay() { xxchangeConsentDisplay = true; checkConsentDisplay(); }
        function checkConsentDisplay() { /*console.log("Getting display information...");*/ amtstack.Get('IPS_SecIOService', checkConsentDisplayResponse1); }

        var xxchangeConsentDisplay = false;
        function checkConsentDisplayResponse1(stack, name, response, status) {
            // console.log('checkConsentDisplayResponse1(' + name + ',' + response + ',' + status + ')');
            if (status == 200) {
                if (response.Body['DefaultScreen']) response.Body['DefaultScreen'] = parseInt(response.Body['DefaultScreen']);
                if (response.Body['NumberOfScreens']) response.Body['NumberOfScreens'] = parseInt(response.Body['NumberOfScreens']);
                if (xxchangeConsentDisplay == true) {
                    xxchangeConsentDisplay = false;
                    // Change consent screen settings
                    response.Body['DefaultScreen'] = d6Display.value;
                    amtstack.Put('IPS_SecIOService', response.Body, checkConsentDisplayResponse1);
                } else {
                    d6Display.value = response.Body['DefaultScreen'];
                    QV('d6ThirdDisplay', response.Body['NumberOfScreens'] > 2);
                }
            } else {
                //console.log("Display Error: " + status);
            }
        }

// ###END###{PowerControl}

// ###BEGIN###{Storage}

        //
        // Storage
        //

        var xxStorage = null;
        var xxStorageVendors = [];
        var xxStorageApplications = [];

        function PullStorage() {
            amtFirstPull |= 8;
            wsstack.comm.PerformAjax('', PullStorageResponse, null, 0, '/amt-storage/', 'GET');
        }

        function PullStorageResponse(data, status, tag) {
            if (amtstack.PendingBatchOperations == 0) refreshButtons(true); // If nothing is being done, re-enable refresh buttons
            
            if (status == 200) {
                QV('go21', true); // Show Storage Panel

                var len; // Remove all chars that are below 32, this will allow parsing even the the firmware gives us garbage.
                for (var i = 0; i < 32; i++) { do { len = data.length; data = data.replace(String.fromCharCode(i), ''); } while (len > data.length); }
                //data = '{"information": {"version": 1.1,"realms": 7765759,"user": "admin"},"content": [{"name": "index.htm","size": 38864},{"vendor": "User","app": "SDK","name": "Sample.html","size": 26760,"link": "SDK Sample"},{"vendor": "User","app": "SDK","name": "ws.js","size": 42575,"link": "SDK Sample"},{"vendor": "User","app": "SDK","name": "btp.min.css","size": 121265,"link": "SDK Sample"},{"vendor": "User","app": "SDK","name": "logo.png","size": 2803,"link": "SDK Sample"}]}';
                try { xxStorage = JSON.parse(data); } catch (e) { return; }
                xxStorageVendors = [];
                xxStorageApplications = [];
                var content = xxStorage['content'];

                if (Array.isArray(content)) {
                    // New flat format, convert to tree format.
                    var newcontent = {};
                    for (var i in content) {
                        var vendor = content[i]['vendor'] ? content[i]['vendor'] : '';
                        if (!newcontent[vendor]) { newcontent[vendor] = {}; }
                        var app = content[i]['app'] ? content[i]['app'] : '';
                        if (!newcontent[vendor][app]) { newcontent[vendor][app] = {}; }
                        if (content[i]['name']) { newcontent[vendor][app][content[i]['name']] = content[i]; }
                    }
                    xxStorage['content'] = content = newcontent;
                } else {
                    // Tree format, move index.htm and logon.htm
                    if (content['index.htm'] || content['logon.htm']) { content[''] = { '': {} }; }
                    if (content['index.htm']) { content['']['']['index.htm'] = content['index.htm']; delete content['index.htm']; }
                    if (content['logon.htm']) { content['']['']['logon.htm'] = content['logon.htm']; delete content['logon.htm']; }
                }

                // Display all storage files
                var count = 0, x = TableStart2() + '<tr><td class=r1 style=padding-left:15px><br>' + "Gérez le stockage Intel&reg; AMT pour cet ordinateur." + '<br><br>';
                var ii, jj, xx = '', links = '', linkid = 30;
                for (var i in content) {
                    var jcount = 0;
                    for (var j in content[i]) {
                        jcount++;
                        var kcount = 0;
                        for (var k in content[i][j]) {
                            kcount++;
                            if (i != ii || j != jj) {
                                if (xx != '') { x += xx; xx = '<br>'; }
                                ii = i; jj = j;
                                if (i != '') { xx += EscapeHtml(i + ' / ' + j); } else { xx += "Racine"; }
                            }
                            //var handle = "\"" + i + "\",\"" + j + "\",\"" + k + "\"";
                            var handle = '\"' + i + ((i != '') ? '/' : '') + j + ((j != '') ? '/' : '') + k + '\"';
                            xx += '<div class=itemBar onclick=showStorageDetails("' + i + '","' + j + '","' + k + '",' + handle + ')><div style=float:right>';
                            // ###BEGIN###{Mode-Firmware}
                            xx += AddButton2("Ouvert", 'OpenFromStorage(' + handle + ',event)');
                            // ###END###{Mode-Firmware}
                            // ###BEGIN###{Mode-LMS}
                            xx += ' ' + AddButton2("Ouvert", 'OpenFromStorage(' + handle + ',event)');
                            // ###END###{Mode-LMS}
                            // ###BEGIN###{FileSaver}
                            xx += ' ' + AddButton2("Télécharger", 'DownloadFromStorage(' + handle + ',\"' + k + '\",event)');
                            // ###END###{FileSaver}
                            xx += '</div><div style=padding-top:3px><b>' + EscapeHtml(k) + '</b>, <i>' + content[i][j][k]['size'] + " octets" + '</i></div></div>';
                            // ###BEGIN###{Mode-Firmware}
                            if (content[i][j][k]['link'] && i != '') { links += '<p id=go' + linkid + ' class=nav1 onclick=goiFrame(event,' + linkid + ',"/amt-storage/' + i + '/' + j + '/' + k + '") title="' + i + ' / ' + j + '"><a>' + content[i][j][k]['link'] + '</a></p>'; linkid++; }
                            // ###END###{Mode-Firmware}
                            count++;
                            if (xxStorageVendors.indexOf(i) == -1) xxStorageVendors.push(i);
                            if (xxStorageApplications.indexOf(j) == -1) xxStorageApplications.push(j);
                        }
                        if (kcount == 0) {  // Clear empty application & vendor
                            wsstack.comm.PerformAjax('', function () { }, null, 0, '/amt-storage/' + i + '/' + j, 'DELETE');
                            wsstack.comm.PerformAjax('', function () { }, null, 0, '/amt-storage/' + i, 'DELETE');
                        }
                    }
                    if (jcount == 0) { wsstack.comm.PerformAjax('', function () { }, null, 0, '/amt-storage/' + i, 'DELETE'); } // Clear empty vendor
                }
                if (xx != '') x += xx;
                if (count == 0) { x += '<div style=padding-left:15px><br><i>' + "Aucun fichier trouvé." + '</i></div><br>'; }
                var uploadSupport = false;
                try { var reader = new FileReader(); uploadSupport = ((reader != null) && (reader.readAsBinaryString != null)); } catch (ex) { console.log(ex); }
                x += '<br><td class=r1>' + TableEnd(AddRefreshButton('PullStorage()') + (uploadSupport ? AddButton("Télécharger...", 'UploadToStorage()') : '')
                // ###BEGIN###{Mode-NodeWebkit}
                    //+ AddButton("Upload Application...", 'UploadAppToStorage()')
                // ###END###{Mode-NodeWebkit}
                );
                // ###BEGIN###{Mode-Firmware}
                //QH('storagelinks', links);
                // ###END###{Mode-Firmware}
                QH('id_TableSystemStorage', x);
            } else {
                QH('id_TableSystemStorage', "Impossible de charger les données de stockage ..." + '<br/>' + AddButton("Rafraîchir", 'PullStorage()'));
            }
        }

        function showStorageDetails(i, j, k, h) {
            if (xxdialogMode) return;
            var x = '', item = xxStorage['content'][i][j][k];
            if (i != '') x += addHtmlValue("Vendeur", i);
            if (j != '') x += addHtmlValue("Application", j);
            x += addHtmlValue("Nom", k);
            x += addHtmlValue("Taille", item['size'] + ' bytes');
            if (item['link']) { x += addHtmlValue("Lien", item['link']); }
            setDialogMode(11, "Article de stockage", 5, showStorageDetailsEx, x, h);
        }

        function showStorageDetailsEx(buttons, handle) {
            if (buttons == 2) { wsstack.comm.PerformAjax('', storageDeleteResponse, null, 0, '/amt-storage/' + handle, 'DELETE'); }
        }

        function storageDeleteResponse(data, status) {
            if (status != 200) {
                messagebox("Espace de rangement", format("Impossible de supprimer le fichier (ERR {0}), vérifiez que l'ordinateur est sous tension.", status));
            } else {
                PullStorage();
            }
        }

        // ###BEGIN###{FileSaver}
        function DownloadFromStorage(handle, filename, e) {
            if (xxdialogMode) return;
            haltEvent(e);
            wsstack.comm.PerformAjax('', DownloadFromStorageEx, filename, 0, '/amt-storage/' + handle, 'GET');
        }

        function DownloadFromStorageEx(data, status, tag) {
            if ((status != 200) || (data == null)) { console.log(status, 'Data = null'); return; }
            saveAs(data2blob(data), tag);
        }
        // ###END###{FileSaver}

        function OpenFromStorage(handle, e) {
            if (xxdialogMode) return;
            haltEvent(e);
            // ###BEGIN###{Mode-Firmware}
            var newWindow = window.open('/amt-storage/' + handle, '_blank', 'noopener,noreferrer');
            // ###END###{Mode-Firmware}
            // ###BEGIN###{!Mode-Firmware}
            var newWindow = window.open('http://' + wsstack.comm.host + ':' + wsstack.comm.port + '/amt-storage/' + handle, '_blank', 'noopener,noreferrer');
            // ###END###{!Mode-Firmware}
            newWindow.opener = null;
            newWindow.focus();
        }

        function PushToStorage(vendorAppnameFilename, data, append) {
            var tag = null;
            if (data.length > 7000) { tag = [vendorAppnameFilename, data.substring(7000)]; data = data.substring(0, 7000); }
            wsstack.comm.PerformAjax(data, PushToStorageResponse, tag, 0, '/amt-storage/' + vendorAppnameFilename + (append == true ? '?append=' : ''), 'PUT');
        }

        function PushToStorageResponse(data, status, tag) {
            if (status != 200) { messagebox("Espace de rangement", format("Impossible de pousser le fichier (ERR {0}), vérifiez que l'ordinateur est sous tension.", status)); } else {
                if (tag != null) { PushToStorage(tag[0], tag[1], true); } else { PullStorage(); }
            }
        }

        function UploadToStorage(file, filename) {
            if (xxdialogMode) return;
            if (!filename) { filename = ''; }
            var x = '';
            x += '<br>' + "Sélectionnez un petit fichier à télécharger vers le stockage et entrez un fournisseur, une application et un nom de fichier." + '<br>';
            if (!file) {
                x += '<br><div style=height:20px><input type=file id=mstoragefile style=float:right;width:240px onchange=SetStorageName()><div>Upload file</div></div>';
            } else {
                x += '<br><div style=height:20px><input id=mstoragefile style=float:right;width:240px readonly disabled=disabled value="' + filename + '" ><div>' + "Téléverser un fichier" + '</div></div>';
            }
            x += '<br><div style=height:16px><input id=mstoragevendor placeholder="' + "Vendeur" + '" list=mstoragevendorlist maxlength=11 style=float:right;width:240px><div>' + "Nom du vendeur" + '</div></div>';
            x += '<br><div style=height:16px><input id=mstorageapplication placeholder="' + "App" + '" list=mstorageapplicationlist maxlength=11 style=float:right;width:240px><div>' + "Nom de l'application" + '</div></div>';
            x += '<br><div style=height:16px><input id=mstoragefilename placeholder="' + "Nom de fichier" + '" maxlength=11 style=float:right;width:240px><div>' + "Nom de fichier" + '</div></div>';
            x += '<br><div style=height:16px><input id=mstoragetype placeholder=application/octet-stream list=mstoragetypelist style=float:right;width:240px><div>' + "Type MIME" + '</div></div>';
            x += '<br><div style=height:16px><input id=mstoragelink style=float:right;width:240px><div title=\"' + "S'il est défini, crée un lien vers ce contenu à partir de la page Web principale" + '\">' + "Lien" + '</div></div><br>';
            x += '<datalist id=mstoragevendorlist>';
            for (var i in xxStorageVendors) { x += '<option value="' + xxStorageVendors[i] + '">'; }
            x += '</datalist>';
            x += '<datalist id=mstorageapplicationlist>';
            for (var i in xxStorageApplications) { x += '<option value="' + xxStorageApplications[i] + '">'; }
            x += '</datalist><datalist id=mstoragetypelist><option value="application/octet-stream"><option value="image/jpeg"><option value="text/html"><option value="text/plain"></datalist>';
            setDialogMode(11, "Téléchargement de stockage", 3, UploadToStorageEx, x, file);
            if (file) { SetStorageName(filename); }
        }

        // ###BEGIN###{Mode-NodeWebkit}
        /*
        var UploadAppToStorageFileList;
        function UploadAppToStorage() {
            if (xxdialogMode) return;
            require('fs').readdir('.', function read(err, data) {
                var filelist = [], filecount = 0;
                if (err == null) { for (var i in data) { if ((data[i].endsWith('.gz')) || (data[i].endsWith('.br'))) { filelist.push(data[i]); filecount++; } } }
                if (filecount > 0) {
                    var x = '';
                    x += "Select the web application to upload, this will replace the Intel&reg; AMT default web pages." + '<br><br><div style=height:26px><select id=mwebappsel style=float:right;width:240px>';
                    for (var i in filelist) { x += '<option value=' + i + '>' + filelist[i].substring(0, filelist[i].length - 3) + '</option>'; }
                    x += '</select><div>' + "Web Application" + '</div></div>';
                    setDialogMode(11, "Storage Application Upload", 3, UploadAppToStorageEx, x, filelist);
                }
            });
        }

        function UploadAppToStorageEx(b, filelist) {
            var file = filelist[Q('mwebappsel').value];
            require('fs').readFile(file, 'binary', function read(err, data) {
                if (err == null) { PushToStorage('index.htm', '<metadata><headers><h>Content-Encoding: ' + (file.endsWith('.br')?'br':'gzip') + '</h><h>Content-Type: text/html</h></headers></metadata>' + data); }
            });
        }
        */
        // ###END###{Mode-NodeWebkit}

        function UploadToStorageEx(button, tag) {
            if (!tag) {
                var x = Q('mstoragefile');
                if (x.files.length != 1) return;
                var reader = new FileReader();
                reader.onload = UploadToStorageEx2;
                reader.filename = x.files[0].name;
                reader.readAsBinaryString(x.files[0]);
            } else {
                var reader = new FileReader();
                reader.onload = UploadToStorageEx2;
                reader.filename = Q('mstoragefile').value;
                reader.readAsBinaryString(tag);
            }
        }

        function SetStorageName(filename) {
            if (!filename) {
                var x = Q('mstoragefile');
                if (x.files.length == 1) { filename = x.files[0].name; } else { filename = ''; }
            }
            filename = filename.split(' ').join('');
            var filenameSplit = filename.split('-');
            if (filenameSplit.length == 3 && filenameSplit[0].length < 12 && filenameSplit[1].length < 12) {
                Q('mstoragevendor').value = filenameSplit[0];
                Q('mstorageapplication').value = filenameSplit[1];
                filename = filenameSplit[2];
            }
            filename = filename.split('-').join('');
            if (filename.endsWith('.gz')) filename = filename.substring(0, filename.length - 3);
            if (filename.endsWith('.htm') || filename.endsWith('.html')) Q('mstoragetype').value = 'text/html';
            else if (filename.endsWith('.txt')) Q('mstoragetype').value = 'text/plain';
            if (filename.length > 11) filename = filename.substring(0, 11);
            Q('mstoragefilename').value = filename;
        }

        function UploadToStorageEx2(file) {
            var vaf, vendor = Q('mstoragevendor').value;
            var app = Q('mstorageapplication').value;
            var filename = Q('mstoragefilename').value;
            if (filename == '') filename = 'Filename';
            var mimetype = Q('mstoragetype').value;
            if (mimetype == '') mimetype = 'application/octet-stream';
            var link = Q('mstoragelink').value;
            if (vendor == '' && app == '' && (filename.toLowerCase() == 'logon.htm' || filename.toLowerCase() == 'index.htm')) {
                vaf = filename.toLowerCase();
            } else {
                if (vendor == '') vendor = 'Vendor';
                if (app == '') app = 'App';
                vaf = vendor + '/' + app + '/' + filename;
            }

            var data = '<metadata><headers>';
            var filename = file.target.filename;
            if (!filename) { filename = Q('mstoragefile').files[0].name; }
            if (filename.endsWith('.gz')) { data += '<h>Content-Encoding: gzip</h>'; }
            data += '<h>Content-Type: ' + mimetype + '</h></headers>'; // <h>X-UA-Compatible: IE=Edge</h>
            if (link != '') data += '<link>' + link + '</link>';
            data += '</metadata>' + file.target.result;

            PushToStorage(vaf, data);
        }

// ###END###{Storage}

// ###BEGIN###{Alarms}

        //
        // Alarm Panel
        //

        function _fmtdatetime(str) {
            return str.replace('T',' ').replace('Z','');
        }

        function _fmtinterval(str) {
            var cl = str.replace('T', '').substring(str.indexOf('P') + 1);
            cl = ' ' + cl.replace('D', " journées").replace('H', " heures").replace('M'," minutes");
            cl = cl.replace(" 1 jour", " Un jour").replace(" 1 heure", " 1 heure").replace(" 1 minutes "," 1 minute ");
            return cl.substring(0, cl.length - 1);
        }

        function _fmttimepad(str) {
            str = '' + str;
            while (str.length < 2) { str = '0' + str; }
            return str;
        }

        var xxAlarms = null;

        function PullAlarms() {
            var x = TableStart2() + '<tr><td class=r1 style=padding-left:15px><br>' + "Gérez les alarmes de réveil." + '<br><br>';
            amtstack.Enum('IPS_AlarmClockOccurrence', function(stack, name, response, status) {
                if (status == 200) {
                    QV('go23', true);
                    if (response.length > 0) {
                        xxAlarms = response;
                        for (var i = 0; i < response.length; i++) {
                            var waketime = new Date(response[i]['StartTime']['Datetime']);
                            var details = '<b>' + response[i]['ElementName'] + '</b>, ' + "réveiller sur" + ' ' + waketime.toLocaleString().replace(', ', " à");
                            if (response[i]['Interval'] != undefined) { details += " et chacun" + _fmtinterval(response[i]['Interval']['Interval']); }
                            if (response[i]['DeleteOnCompletion'] == true) { details += ", supprimer une fois terminé"; }
                            x += '<div class=itemBar onclick=showAlertDetails(' + i + ')><div style=float:right>';
                            if (xxAccountAdminName) x += ' ' + AddButton2("Éditer...", 'showAddAlarm(" + i + ")');
                            x += '</div><div style=padding-top:3px;width:auto;float:left;overflow-x:hidden>' + details + '</div></div>';
                        }
                    } else {
                        xxAlarms = null;
                        x += '<div style=padding-left:15px><br><i>' + "Aucune alarme de réveil enregistrée." + '</i></div><br>';
                    }
                    var y = '<div>&nbsp;' + AddRefreshButton('PullAlarms()');
                    if (xxAccountAdminName) { y += AddButton2("Supprimer toutes les alarmes", 'RemoveAllAlarms()', xxAlarms ? '' : 'disabled') + AddButton("Ajouter", 'showAddAlarm()'); }
                    x += '<br><td class=r1>' + TableEnd(y + '</div>');
                    QH('id_TableAlarm', x);
                }
            }, null, true);
        }

        function prepareAlarmOccurenceTemplate(id, nm, start, interval, del) {
            return '<d:AlarmTemplate xmlns:d=\"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_AlarmClockService\" xmlns:s=\"http://intel.com/wbem/wscim/1/ips-schema/1/IPS_AlarmClockOccurrence\"><s:InstanceID>' + id + '</s:InstanceID><s:StartTime><p:Datetime xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + start + '</p:Datetime></s:StartTime><s:Interval><p:Interval xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + interval + '</p:Interval></s:Interval><s:DeleteOnCompletion>' + del + '</s:DeleteOnCompletion></d:AlarmTemplate>';
        }
        
        function RemoveAllAlarms(){
            setDialogMode(1, "Supprimer toutes les alarmes de réveil", 3, RemoveAllAlarmsEx, "Confirmer la suppression de toutes les alarmes de réveil?");
        }

        function RemoveAllAlarmsEx() {
            var deleteCount = xxAlarms.length;
            for (var a in xxAlarms) { amtstack.Delete('IPS_AlarmClockOccurrence', xxAlarms[a], function(stack, name, response, status) { if (--deleteCount == 0) { PullAlarms(); }}); }
        }

        function showAddAlarm(alrm){
            if (xxdialogMode) return;
            QE('d25alarm_name', !alrm);
            if (alrm != undefined) {
                var alarm = xxAlarms[alrm], waketime = new Date(alarm['StartTime']['Datetime']);
                Q('d25alarm_name').value = alarm['ElementName'];
                Q('d25alarm_sdate').value = waketime.getFullYear() + '-' + _fmttimepad(waketime.getMonth() + 1) + '-' + _fmttimepad(waketime.getDate());
                Q('d25alarm_stime').value = waketime.getHours() + ':' + _fmttimepad(waketime.getMinutes()) + ':' + _fmttimepad(waketime.getSeconds());
                if (alarm['Interval']) {
                    var j = alarm['Interval']['Interval'].replace('P','').replace('T','').replace('D','D,').replace('H','H,').replace('M','M,').split(','), k = [0, 0, 0];
                    for (var i in j) {
                        var jl = j[i].length - 1;
                        if (j[i][jl] == 'D') { k[0] = parseInt(j[i].substring(0, jl)); }
                        if (j[i][jl] == 'H') { k[1] = parseInt(j[i].substring(0, jl)); }
                        if (j[i][jl] == 'M') { k[2] = parseInt(j[i].substring(0, jl)); }
                    }
                    Q('d25alarm_interval').value = k.join('-');
                } else {
                    Q('d25alarm_interval').value = '';
                }
                Q('d25alarm_doc').value = (alarm['DeleteOnCompletion'] == true)?1:0;
            } else {
                var currentTime = new Date();
                currentTime.setDate(new Date().getDate() + 1);
                Q('d25alarm_name').value = '';
                Q('d25alarm_sdate').value = currentTime.getFullYear() + '-' + _fmttimepad(currentTime.getMonth() + 1) + '-' + _fmttimepad(currentTime.getDate());
                Q('d25alarm_stime').value = currentTime.getHours() + ':' + _fmttimepad(currentTime.getMinutes()) + ':00';
                Q('d25alarm_interval').value = '';
                Q('d25alarm_doc').value = 0;
            }
            setDialogMode(25, "Ajouter une nouvelle alarme", (alrm != undefined)?7:3, showAddAlarmOk, '', alrm);
            alertDialogUpdate();
        }

        function alertDialogUpdate() {
            var il = Q('d25alarm_interval').value.split('-').length;
            var ok = (Q('d25alarm_name').value.length > 0) && (Q('d25alarm_sdate').value.split('-').length == 3) && (Q('d25alarm_stime').value.split(':').length == 3) && ((il == 1) || (il == 3));
            QE('idx_dlgOkButton', ok);
        }

        function showAddAlarmOk(button, alrm) {
            if (button == 2) { showAlertDetailsDelete(button, alrm); return; }
            var alarm_name = Q('d25alarm_name').value;
            var x1 = Q('d25alarm_sdate').value.split('-');
            var x2 = Q('d25alarm_stime').value.split(':');
            var t = new Date(x1[0], x1[1] - 1, x1[2], x2[0], x2[1], x2[2], 0); // Month is 0 = JAN, 11 = DEC
            var alarm_starttime = _fmttimepad(t.getUTCFullYear()) + '-' + _fmttimepad(t.getUTCMonth() + 1) + '-' + _fmttimepad(t.getUTCDate()) + 'T' + _fmttimepad(t.getUTCHours()) + ':' + _fmttimepad(t.getUTCMinutes()) + ':' + _fmttimepad(t.getUTCSeconds()) + 'Z';
            var x = Q('d25alarm_interval').value.split('-');
            if (x.length != 3) { x = [0, 0, 0]; }
            var alarm_interval = 'P' + x[0] + 'DT' + x[1] + 'H' + x[2] + 'M';
            var alarm_doc = (Q('d25alarm_doc').value == 1);
            var tpl = prepareAlarmOccurenceTemplate(alarm_name, alarm_name, alarm_starttime, alarm_interval, alarm_doc);
            if (alrm == undefined) {
                wsstack.ExecMethodXml(amtstack.CompleteName('AMT_AlarmClockService'), 'AddAlarm', tpl,
                    function (ws, resuri, response, status) {
                        if (status != 200) { messagebox("Ajouter une alarme", format("Impossible d'ajouter l'alarme. Statut: {0}. <br/> Vérifiez que l'alarme est pour une heure future.", status)); return; }
                        if (response.Body['ReturnValue'] != 0) { messagebox("Ajouter une alarme", format("Échec de l'ajout de l'alarme {0}. <br/> Vérifiez que l'alarme est pour une heure future.", response.Body['ReturnValueStr'])); return; }
                        PullAlarms();
                    }
                );
            } else {
                var alarmx = Clone(xxAlarms[alrm]);
                alarmx['StartTime'] = '<p:Datetime xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + alarm_starttime + '</p:Datetime>';
                alarmx['Interval'] = '<p:Interval xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + alarm_interval + '</p:Interval>';
                alarmx['DeleteOnCompletion'] = alarm_doc;
                amtstack.Put('IPS_AlarmClockOccurrence', alarmx, function (ws, resuri, response, status) {
                    if (status != 200) { messagebox("Modifier l'alarme", format('Failed to change alarm. Status: {0}.<br/>Verify the alarm for at a future time.', status)); return; }
                    PullAlarms();
                }, null, null, { 'InstanceID' : alarmx['InstanceID']});
            }
        }

        function showAlertDetails(i) {
            if (xxdialogMode) return;
            var alarm = xxAlarms[i], waketime = new Date(alarm['StartTime']['Datetime']);
            var x = '<div style=text-align:left>' + addHtmlValue("Nom", alarm['ElementName']) + addHtmlValue("Heure de réveil", waketime.toLocaleString().replace(', ', ' at '));
            if (alarm['Interval'] != undefined) { x += addHtmlValue("Interne", _fmtinterval(alarm['Interval']['Interval'])); }
            x += addHtmlValue("Après le réveil", (alarm['DeleteOnCompletion'] == true)?"Supprimer l'alarme":"Garder l'alarme") + '</div>';
            messagebox(format("Alarme {0}", alarm['ElementName']), x);
            setDialogMode(11, "Alarme" + alarm['ElementName'], 5, showAlertDetailsDelete, x, i);
        }

        function showAlertDetailsDelete(button, tag) {
            if (button == 2) { amtstack.Delete('IPS_AlarmClockOccurrence', xxAlarms[tag], function(stack, name, response, status) { PullAlarms(); }); }
        }

// ###END###{Alarms}

// ###BEGIN###{Scripting}

        //
        // Scripting
        //

        // Called by the "Run Script..." button. Display a dialog box to ask for the script file.
        function script_runScriptDlg() {
            if (xxdialogMode || scriptstate) return;
            setDialogMode(11, "Script de lancement", 3, script_runScriptDlgOk, '<br><input id=scriptopen type=file style=width:100% accept=.mescript>');
        }

        // Once the script file is selected, decode the script here.
        function script_runScriptDlgOk(r) {
            if (r != 1) return;
            var x = Q('scriptopen');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = script_onScriptRead;
            reader.readAsBinaryString(x.files[0]);
        }

        // Called once the script is decoded, get the script setup and start running it.
        function script_onScriptRead(file) {
            var x;
            try { x = JSON.parse(file.target.result); } catch (e) {}
            // ###BEGIN###{Scripting-Editor}
            if (currentView == 20) {
                // Load script into editor
                if (x['scriptText']) Q('scriptarea').value = x['scriptText'];
                if (x['mescript']) Q('compiledarea').value = rstr2hex(atob(x['mescript']));
                if (x['blocks']) { script_setBuildBlocks(x['blocks']); scriptViewButton(1); } else { script_setBuildBlocks(); scriptViewButton(0); }
                if (x['scriptBlocks']) { script_BlockScript = x['scriptBlocks']; } else { if (!script_BuildingBlocks) { script_BlockScript = []; } }

                // Update the scriptBlocks to the latest blocks. This is does because we may update an existing script to new blocks.
                for (var i in script_BlockScript) {
                    var block = script_BlockScript[i];
                    var xblock = script_BuildingBlocks[block['xname']];
                    if (xblock) {
                        var b = Clone(xblock); // Clone a new block, then set all the variables.
                        b['id'] = block['id'];
                        b['xname'] = block['xname'];
                        for (var j in b.vars) { if (block.vars[j]) { b.vars[j]['value'] = block.vars[j]['value']; } }
                        script_BlockScript[i] = b;
                    }
                }

                // Reset the script state
                fupdatescript();
                delete scriptstate;
                resetScriptButton();
                return;
            }
            // ###END###{Scripting-Editor}
            var startvars = { '_interactive':1 };
            // ###BEGIN###{Certificates}
            startvars['_certificates'] = 1;
            // ###END###{Certificates}
            // ###BEGIN###{!Mode-Firmware}
            startvars['_mode'] = 'Firmware';
            // ###END###{!Mode-Firmware}
            // ###BEGIN###{!Mode-MeshCentral2}
            startvars['_mode'] = 'MeshCentral2';
            // ###END###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-NodeWebkit}
            startvars['_mode'] = 'NodeWebkit';
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{Mode-LMS}
            startvars['_mode'] = 'LMS';
            // ###END###{Mode-LMS}
            // ###BEGIN###{Mode-WebSite}
            startvars['_mode'] = 'WebSite';
            // ###END###{Mode-WebSite}
            if (x && x['mescript']) scriptstate = script_setup(atob(x['mescript']), startvars);
            if (scriptstate) {
                scriptstate.wsstack = wsstack;
                scriptstate.amtstack = amtstack;
                scriptstate.onStep = script_updateScriptState;
                scriptstate.onConsole = script_console;
                scriptstate.start(100);
            } else {
                messagebox("Script de lancement", "Fichier de script non valide.");
            }
        }

        // Called when the script changes state, displays the green status bar at the top of the web page.
        function script_updateScriptState() {
            if (scriptstate) {
                QV('id_scriptstatus', scriptstate.state > 0); center();
                if (scriptstate.state == 0) {
                    // ###BEGIN###{Mode-NodeWebkit}
                    if (urlvars['autoexit']) { // Exit if script finished running
                        require('nw.gui').Window.get().close();
                        //require('nw.gui').App.quit();
                        return;
                    }
                    // ###END###{Mode-NodeWebkit}
                    scriptstate = undefined;
                }
            }
        }

        // Called by a running script to update the console. The last message in the console is displayed in the top green bar.
        function script_console(msg) {
            if (msg.indexOf('INFO: ') == 0) { msg = msg.substring(6); }
            if (msg.indexOf('SUCCESS: ') == 0) { msg = msg.substring(9); }
            if (msg.indexOf('ERROR: ') == 0) { msg = msg.substring(7); }
            QH('id_scriptstatusstr', ', ' + msg);
        }

        // Called by the "Stop" button on the script status bar. Causes the script to stop.
        function script_Stop() {
            if (scriptstate) {
                if (scriptstate.dialog == true) { setDialogMode(0); }
                scriptstate.stop();
                scriptstate.state = 0;
                script_updateScriptState();
            }
        }

// ###END###{Scripting}

// ###BEGIN###{Scripting-Editor}
        
        var script_BuildingBlocks; // List of block that can be used to build a script. This is shown on the list side.
        var script_StartingBuildingBlocks; // List of block that can be used to build a script when you get started.
        var script_BlockScript = []; // List of blocks that are part of the current script.
        var script_BlockScriptSelectedId = null; // The identifier of the currently selected block.
        var script_BuilderView = 0; // 0 = Editor View, 1 = Builder View
        var editscriptstate; // This is the instance of the script runner used by the editor. This is different from the runner used by the web page.

        // ###BEGIN###{!Mode-Firmware}
        function scriptLoadStartingBlocks() {
            // ###BEGIN###{!Mode-NodeWebkit}
            var request = new XMLHttpRequest();
            request.onload = function() {
                if (request.status >= 200 && request.status < 400) {
                    // Success
                    var x;
                    try { x = JSON.parse(request.responseText); } catch (e) {}
                    if ((x) && (x['blocks'])) { script_StartingBuildingBlocks = x['blocks']; script_setBuildBlocks(script_StartingBuildingBlocks); }
                }
            };
            request.onerror = function() { console.log('Failed to get script blocks'); };
            request.open('GET', 'scriptblocks.txt', true);
            request.send();
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var content;
            require('fs').readFile('scriptblocks.txt', 'utf8', function read(err, data) {
                if (err == null) {
                    var x;
                    try { x = JSON.parse(data); } catch (e) {}
                    if (x['blocks']) { script_StartingBuildingBlocks = x['blocks']; script_setBuildBlocks(script_StartingBuildingBlocks); }
                }
            });
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{!Mode-Firmware}

        // Called by the "View Editor" or "View Builder" button to toggle between the view modes.
        // If there is no construction blocks, display the script editor only.
        function scriptViewButton(x) {
            script_BuilderView = x;
            QV('scripteditor', x == 0);
            QV('scriptbuilder', x == 1);
            QV('viewEditorButton', script_BuildingBlocks && (x == 1));
            QV('viewBuilderButton', script_BuildingBlocks && (x == 0));
        }

        // Display the list of construction script block on the left side.
        function script_setBuildBlocks(blocks) {
            script_BuildingBlocks = blocks;
            var x = '';
            if (blocks) {
                for (var i in blocks) {
                    if (i.charCodeAt(0) != 95) {
                        x += '<div id=sblock_' + i + ' style=cursor:pointer;background-color:#ccc;width:auto;padding:5px;margin:2px ondblclick=script_faddblock("' + i + '") draggable=true ondragstart=script_fondragstart(event,this) ondragend=script_fondragend(event,this) title="' + blocks[i]['desc'] + '"';
                        // ###BEGIN###{ContextMenus}
                        var cmenus = [];
                        cmenus.push("Ajouter" + '#script_faddblock("' + i + '")');
                        cmenus.push("Éditer..." + '#script_feditblock("' + i + '")');
                        x += ' cm=\"' + cmenus.join('|') + '\"';
                        // ###END###{ContextMenus}
                        x += '>' + blocks[i]['name'] + '</div>';
                    }
                }
            }
            QH('blocks', x);
            script_fonfilterchanged();
            scriptViewButton(script_BuildingBlocks?1:0);
        }

        // Add a new block to the end of the block script. This is called when you right click on a block and hit "Add" in the context menu.
        function script_faddblock(h) {
            var b = Clone(script_BuildingBlocks[h]); // To add a new block to the script, clone the block, assign it a random id and set the xname to the name of the block.
            b['id'] = Math.random();
            b['xname'] = h;
            script_BlockScript.push(b); // Now that a block is created, add it at the end of the script and set it as the selected block.
            script_BlockScriptSelectedId = script_BlockScript.length - 1;
            fupdatescript(); // Re-display the list of script blocks. The selected block will also be highlighted.
        }

        // Edit a script block
        function script_feditblock(h) {
            if (xxdialogMode) return;
            setDialogMode(11, format("Modifier {0}", script_BuildingBlocks[h]['name']), 3, script_feditblockEx, 'Edit this block? This operation will reset the block editor and load the block code into the code editor.', h);
        }

        // Called when the script block edit dialog is closed.
        function script_feditblockEx(button, h) {
            script_newScriptDlgOk();
            scriptViewButton(0);
            var x = '', b = script_BuildingBlocks[h];
            x += '##!BLOCK!##\r\n#id=' + h + '\r\n#name=' + b['name'] + '\r\n#desc=' + b['desc'] + '\r\n##!BLOCK!##\r\n';
            for (var i in b['vars']) {
                var v = b['vars'][i];
                x += '##!VAR!##\r\n#id=' + i + '\r\n#name=' + v['name'] + '\r\n#desc=' + v['desc'] + '\r\n#type=' + v['type'] + '\r\n';
                if (v['maxlength']) { x += '#maxlength=' + v['maxlength'] + '\r\n'; }
                if (v['values']) { for (var j in v['values']) { x += '#values-' + j +'=' + v['values'][j] + '\r\n'; } }
                x += '#value=' + v['value'] + '\r\n##SWAP %%%' + i + '%%% ' + v['value'] + '\r\n';
            }
            x += '##!VAR!##\r\n##SWAP %%%~%%% 0\r\n\r\n##!BLOCK!##\r\n' + b['code'] + '\r\n##!BLOCK!##\r\n';
            Q('scriptarea').value = x;
        }

        function script_fConvertScriptToJsonBlock(script) {
            var result = {}, scriptparts = script.split('##!BLOCK!##\n'), scriptlines = scriptparts[1].split('\n');

            // Parse information part
            for (var i in scriptlines) {
                var s = scriptlines[i].split('=');
                if (s.length == 2) { result[s[0].substring(1)] = s[1]; }
            }

            // Parse variables part
            result['vars'] = {};
            scriptvariables = scriptparts[2].split('##!VAR!##\n');
            for (var i in scriptvariables) {
                scriptlines = scriptvariables[i].split('\n');
                var v = {}, values = {}, valueslen = 0;
                for (var j in scriptlines) {
                    var s = scriptlines[j].split('=');
                    if ((s.length == 2) && (s[1])) {
                        if ((s[0]) && (s[0].length > 0)) {
                            if (s[0].substring(0, 8) == '#values-') {
                                values[s[0].substring(8)] = s[1];
                                valueslen++;
                            } else {
                                v[s[0].substring(1)] = s[1];
                            }
                        }
                    }
                }
                if (v.id) {
                    if (valueslen > 0) { v['values'] = values; }
                    var id = v.id;
                    delete v.id;
                    result['vars'][id] = v;
                }
            }

            // Parse code part
            result['code'] = scriptparts[3];

            // Package the result
            var id = result.id;
            delete result.id;
            var r = {};
            r[id] = result;
            return JSON.stringify(r, null, '  ');
        }

        /*
        // If the delete key is pressed, delete the block
        function script_fonkeypress(e) {
            if (xxdialogMode) return;
            if (e.key == 'Delete' && script_BlockScriptSelectedId != null) {
                //delete script_BlockScript[script_BlockScriptSelectedId];
                script_BlockScript.splice(script_BlockScriptSelectedId, 1);
                script_BlockScriptSelectedId = null;
                fupdatescript();
            }
        }
        */

        // Filer the list of blocks on the left side list.
        function script_fonfilterchanged() {
            var filter = Q('blockfilter').value.toLowerCase();
            for (var i in script_BuildingBlocks) {
                // Script blocks that start with "_" are hidden blocks and should never be shown.
                if (i.charCodeAt(0) != 95) { QV('sblock_' + i, (script_BuildingBlocks[i]['name'].toLowerCase().indexOf(filter) >= 0 || script_BuildingBlocks[i]['desc'].toLowerCase().indexOf(filter) >= 0)); }
            }
        }

        // Called when you click on a block. If you double click, on a block, do like pressing on the "Edit..." button.
        var script_fonclickDblClickDetectIndex = null;
        var script_fonclickDblClickDetectTime = null;
        function script_fonclick(e, t) {
            // ###BEGIN###{ContextMenus}
            hideContextMenu(); // Any click on this area must close the context menu
            // ###END###{ContextMenus}
            if (xxdialogMode) return;
            script_BlockScriptSelectedId = null;
            if (t) { t = fgetParentWithId(t); if (t.id.startsWith('xblock_')) { script_BlockScriptSelectedId = t.id.substring(7); } } // Figure out what block was clicked on
            fupdatescript(); // This will show the currently selected block in a different color.
            haltEvent(e);

            // Figure out if this is a double click. We need two clicks on the same object within 250ms.
            if (script_fonclickDblClickDetectIndex == script_BlockScriptSelectedId && (new Date().getTime() - script_fonclickDblClickDetectTime) < 250) { return script_foneditclick(script_BlockScriptSelectedId); }
            script_fonclickDblClickDetectIndex = script_BlockScriptSelectedId;
            script_fonclickDblClickDetectTime = new Date().getTime();
        }

        // Script block drag & drop functions, allow the user to create and move script blocks.
        function script_fondragstart(e, t) { if (xxdialogMode) return; t = fgetParentWithId(t); t.style.opacity = '0.4'; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('scriptbuilder/block', t.id); }
        function script_fondragend(e, t)   { if (xxdialogMode) return; t = fgetParentWithId(t); t.style.opacity = '1.0'; }
        function script_fondragenter(e, t) { if (xxdialogMode) return; fgetParentWithId(t).style['border-top'] = 'solid 2px black'; }
        function script_fondragleave(e, t) { if (xxdialogMode) return; e = e.originalEvent || e; var currentElement = document.elementFromPoint(e.pageX, e.pageY); if (!t.contains(currentElement)) { fgetParentWithId(t).style['border-top'] = 'none'; } }

        // Called when you drop a block on the block script area. This code will add or move a block into it's new place.
        function script_fondrop(e, t) {
            if (xxdialogMode) return;
            t = fgetParentWithId(t);
            var b, x = e.dataTransfer.getData('scriptbuilder/block'), dp = parseInt(t.id.substring(7));
            if (x == '') { documentFileSelectHandler(e); return; }
            if (x.startsWith("sblock_")) {
                // Create a new script block
                b = Clone(script_BuildingBlocks[x.substring(7)]);
                b['id'] = Math.random();
                b['xname'] = x.substring(7);
            } else {
                // Pull an existing script block from the list
                var i = parseInt(x.substring(7));
                b = script_BlockScript[i];
                script_BlockScript.splice(i, 1);
                if (dp > i) dp--;
            }
            if (t.id == 'scriptblocks') {
                // Put the block at the end of the list
                if (b) script_BlockScript.push(b);
                script_BlockScriptSelectedId = script_BlockScript.length - 1;
            } else {
                // Insert the block within the list, above the drop point
                script_BlockScript.splice(dp, 0, b);
                script_BlockScriptSelectedId = dp;
            }
            fupdatescript();
            haltEvent(e);
        }

        // Called when you hit "Edit..." on a block, displays a dialog box with all block attributes.
        function script_foneditclick(h) {
            if (xxdialogMode) return;
            var block = script_BlockScript[h];
            script_BlockScriptSelectedId = h;
            fupdatescript();

            if (block != null) {
                var b = block['vars'] ? 7 : 5;
                var c = block['desc'] + '<br><br>';
                if (block['vars']) {
                    // For each variable in a block, add the proper input control for this variable and set the control to the current value.
                    for (var i in block['vars']) {
                        var d = block['vars'][i]['value'];
                        var attributes = '';
                        // Block values can be on type 1:Text,2:Number,3:DropDownList,4:password,5:MultiSelect
                        if (block['vars'][i]['maxlength']) attributes += (' maxlength=' + block['vars'][i]['maxlength']);
                        if (block['vars'][i]['type'] == 2) { attributes += ' onkeypress=\'return numbersOnly(event)\'' }
                        if (block['vars'][i]['type'] == 1 || block['vars'][i]['type'] == 2) { d = '<input title="' + block['vars'][i]['desc'] + '" id=scriptXvalue_' + i + ' value="' + block['vars'][i]['value'] + '" ' + attributes + ' style=width:100%></input>'; }
                        if (block['vars'][i]['type'] == 3) {
                            d = '<select title=\'' + block['vars'][i]['desc'] + '\' id=scriptXvalue_' + i + ' style=width:100%;padding:0;margin:0>';
                            for (var j in block['vars'][i]['values']) { d += '<option value=' + j + (j == block['vars'][i]['value'] ? ' selected' : '') + '>' + block['vars'][i]['values'][j] + '</option>'; }
                            d += '</select>';
                        }
                        if (block['vars'][i]['type'] == 4) { d = '<input type=password autocomplete=off title="' + block['vars'][i]['desc'] + '" id=scriptXvalue_' + i + ' value="' + block['vars'][i]['value'] + '" ' + attributes + ' style=width:100%></input>'; }
                        if (block['vars'][i]['type'] == 5) { d = ''; }
                        if (block['vars'][i]['type'] == 6) { d = '<input type=file title="' + block['vars'][i]['desc'] + '" id=scriptXvalue_' + i + ' ' + attributes + ' style=width:100%></input>'; }
                        c += '<table style=width:100% title="' + block['vars'][i]['desc'] + '"><td style=width:120px>' + block['vars'][i]['name'] + '<td><b>' + d + '</b></table>';
                        if (block['vars'][i]['type'] == 5) {
                            var x = '';
                            c += '<ul id=scriptXvalue_' + i + ' style="list-style-type:none;height:100px;overflow:auto;width:100%;border:1px solid #000;background-color:white;overflow-x:hidden;margin:0;padding:0">';
                            for (var y in block['vars'][i]['values']) {
                                var xc = '';
                                if (block['vars'][i]['value'].indexOf(y) >= 0) xc = ' checked';
                                c += '<li><label><input type=checkbox id=scriptXvaluex_' + i + '-' + y + '' + xc + '>' + block['vars'][i]['values'][y] + '</label></li>';
                            }
                            c += '</ul>';
                        }
                    }
                }
            }

            // Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 11 only)
            setDialogMode(11, block.name, b, script_foneditclickEx, c, h);
        }

        // Called when the script block edit dialog is closed.
        function script_foneditclickEx(button, tag) {
            if (xxdialogMode) return;
            if (button == 2) {
                // Delete this block
                script_BlockScript.splice(tag, 1);
                if (script_BlockScriptSelectedId == tag) { script_BlockScriptSelectedId = null; }
            } else {
                // Change this block with new arguments
                var block = script_BlockScript[tag];
                if (block['vars']) {
                    for (var i in block['vars']) {
                        if (block['vars'][i]['type'] == 5) {
                            block['vars'][i]['value'] = [];
                            for (var y in block['vars'][i]['values']) { if (Q('scriptXvaluex_' + i + '-' + y).checked) block['vars'][i]['value'].push(y); }
                        } else if (block['vars'][i]['type'] == 6) {
                            var x = Q('scriptXvalue_' + i);
                            if (x.files.length == 1) {
                                var reader = new FileReader();
                                reader.onload = function(file) { block['vars'][i]['value'] = btoa(file.target.result); fupdatescript(); };
                                reader.readAsBinaryString(x.files[0]);
                            }
                        } else {
                            block['vars'][i]['value'] = Q('scriptXvalue_' + i).value;
                        }
                    }
                }
            }
            fupdatescript();
        }

        // Starting with a child element, go up one parent at a time until we find an element with an ID.
        function fgetParentWithId(x) { while (!x.id) { x = x.parentElement; } return x; }

        // Displays the list of script blocks to the HTML page. Each block is displayed with it's name, attributes and an edit button.
        function fupdatescript() {
            var x = '';
            for (var i in script_BlockScript) {
                x += '<div id=xblock_' + i + ' style=cursor:pointer;min-height:24px;background-color:#' + ((script_BlockScriptSelectedId == i) ? 'aaa' : 'ccc') + ';width:auto;padding:5px;margin:2px draggable=true onclick=script_fonclick(event,this) ondragenter=script_fondragenter(event,this) ondragleave=script_fondragleave(event,this) ondragstart=script_fondragstart(event,this) ondragend=script_fondragend(event,this) ondrop=script_fondrop(event,this) title="' + script_BlockScript[i]['desc'] + '"';
                // ###BEGIN###{ContextMenus}
                var cmenus = [];
                cmenus.push("Éditer..." + '#script_foneditclick('+i+')');
                cmenus.push("Supprimer" + '#script_foneditclickEx(2,'+i+')');
                x += ' cm=\'' + cmenus.join('|') + '\'';
                // ###END###{ContextMenus}
                x += '><input style=float:right type=button value=Edit... onclick=script_foneditclick(' + i + ')><div style=font-size:16px><b>' + script_BlockScript[i].name + '</b>';
                if (script_BlockScript[i]['vars']) {
                    var r = 0;
                    x += '<table class="scriptBlockVar us" cellpadding=0 cellspacing=0 style=width:100%;border-radius:5px;margin-top:8px>';
                    for (var j in script_BlockScript[i]['vars']) {
                        var v = script_BlockScript[i]['vars'][j]['value'];
                        if (script_BlockScript[i]['vars'][j]['type'] == 4 && script_BlockScript[i]['vars'][j]['value'].length > 0) v = '*****';
                        if (script_BlockScript[i]['vars'][j]['type'] == 3) v = script_BlockScript[i]['vars'][j]['values'][script_BlockScript[i]['vars'][j]['value']];
                        if (script_BlockScript[i]['vars'][j]['type'] == 6) {
                            if (script_BlockScript[i]['vars'][j]['value']) { v = "Fichier binaire," + script_BlockScript[i]['vars'][j]['value'].length + " octets"; } else { v = "Pas encore défini"; }
                        }
                        x += '<tr title="' + script_BlockScript[i]['vars'][j]['desc'] + '"><td width=200px style="' + (r > 0 ? 'border-top:1px solid #a810a8' : '') + '"><p>' + script_BlockScript[i]['vars'][j]['name'] + '<td style="' + (r > 0 ? 'border-top:1px solid #a810a8' : '') + '">' + v;
                        r++;
                    }
                    x += '<tr><td style=height:3px></table>';
                }
                x += '</div></div>';
            }
            if (x == '') { x = '<div style=\"padding:15px;color:gray\">' + "Démarrez votre script en glissant-déposant des blocs du côté gauche dans cette zone de script." + '<div>'; }
            QH('scriptblocks', x + '<div style=height:80px></div>');
            for (var i in script_BlockScript) { QS('xblock_' + i).borderLeft = (script_CurrentHighlightBlock == i) ? '3px solid black' : ''; }
            script_blocksToScript();
        }

        // Convert the list of blocks into a script that can be compiled
        function script_blocksToScript() {
            var script = '';
            if (script_BuildingBlocks) {
                if (script_BuildingBlocks['_start']) { script += '##### Starting Block #####\r\n' + script_BuildingBlocks['_start']['code'] + '\r\n\r\n'; }
                for (var i in script_BlockScript) {
                    var code = script_BlockScript[i]['code'];
                    code = code.split('%%%~%%%').join(i);
                    for (var j in script_BlockScript[i]['vars']) { code = code.split('%%%' + j + '%%%').join(script_BlockScript[i]['vars'][j]['value']); }
                    script += '##### Block: ' + script_BlockScript[i]['name'] + ' #####\r\nHighlightBlock __t ' + i + '\r\n' + code + '\r\n\r\n';
                }
                if (script_BuildingBlocks['_end']) { script += '##### Ending Block #####\r\n' + script_BuildingBlocks['_end']['code'] + '\r\nHighlightBlock\r\n'; }
            }
            Q('scriptarea').value = script;
        }

        // Highlight a script block. This is useful to know what block the script is currently running
        var script_CurrentHighlightBlock;
        function script_HighlightBlock(runner, x) {
            if (runner == editscriptstate) { // Only highlight blocks if the scrpt editor is running the script. If running a script on the page, don't highlight blocks in the editor.
                script_CurrentHighlightBlock = x;
                for (var i in script_BlockScript) { QS('xblock_' + i).borderLeft = (script_CurrentHighlightBlock == i) ? '3px solid black' : ''; }
            }
        }

        // Called by the "New..." button to reset the script editor to the start
        function script_newScriptDlg() {
            if (xxdialogMode) return;
            setDialogMode(11, "Nouveau script", 3, script_newScriptDlgOk, '<br>' + "Réinitialiser et effacer l'éditeur de script?");
        }

        // Clear the script editor
        function script_newScriptDlgOk() {
            script_setBuildBlocks(script_StartingBuildingBlocks);
            script_BlockScript = [];
            script_BlockScriptSelectedId = null;
            delete editscriptstate;
            scriptViewButton(script_BuildingBlocks?1:0);
            QH('variables', '');
            Q('scriptarea').value = '';
            resetScriptButton();
        }

        // Compile and reset a script to the starting position
        function resetScriptButton() {
            // Compile the script
            breakScriptButton();
            Q('compiledarea').value = rstr2hex(script_compile(Q('scriptarea').value, function(m) { messagebox("Erreur de compilation de script", m); }));
            delete editscriptstate;

            // Reset the script environment
            Q('console').value = '';
            QH('variables', '');
            QH('EditScriptStatus', "Arrêté");
            if (script_BuilderView == 1) { fupdatescript(); }
            if (Q('compiledarea').value.length == 0) return;

            // Create a new script runtime object
            var startvars = { '_interactive':1 };
            // ###BEGIN###{Certificates}
            startvars['_certificates'] = 1;
            // ###END###{Certificates}
            // ###BEGIN###{!Mode-Firmware}
            startvars['_mode'] = 'Firmware';
            // ###END###{!Mode-Firmware}
            // ###BEGIN###{!Mode-MeshCentral2}
            startvars['_mode'] = 'MeshCentral2';
            // ###END###{!Mode-MeshCentral2}
            // ###BEGIN###{Mode-NodeWebkit}
            startvars['_mode'] = 'NodeWebkit';
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{Mode-LMS}
            startvars['_mode'] = 'LMS';
            // ###END###{Mode-LMS}
            // ###BEGIN###{Mode-WebSite}
            startvars['_mode'] = 'WebSite';
            // ###END###{Mode-WebSite}
            editscriptstate = script_setup(hex2rstr(Q('compiledarea').value), startvars);
            editscriptstate.wsstack = wsstack;
            editscriptstate.amtstack = amtstack;
            editscriptstate.onStep = editscript_updateScriptState;
            editscriptstate.onConsole = editscript_console;
            editscript_updateScriptState(editscriptstate);
        }

        // Start running the script
        function runScriptButton() {
            if (editscriptstate == null) resetScriptButton();
            if (editscriptstate == null) return;
            editscriptstate.start(100);
        }

        // Stop/Pause the script
        function breakScriptButton() {
            if (editscriptstate == null) return;
            editscriptstate.stop();
        }

        // Run one step of the script
        function stepScriptButton() {
            if (editscriptstate == null) resetScriptButton();
            if (editscriptstate == null) return;
            breakScriptButton();
            editscriptstate.step();
        }

        // Display a new line into the script console
        function editscript_console(msg) {
            Q('console').value += (msg + '\n');
        }

        // Update the script state information and displayed variables
        var script_states = ["Arrêté", "Fonctionnement", "En pause"];
        function editscript_updateScriptState(runstate) {
            // Update variables
            var r = '';
            if (runstate && runstate != null) {
                var vs = [];
                for (var i in runstate.variables) { if (!i.startsWith('__')) vs.push(i); }
                vs.sort();
                //for (var i in vs) { r += vs[i] + ' = ' + script_toString(runstate.variables[vs[i]]) + "\n"; }
                for (var i in vs) {
                    if (typeof runstate.variables[vs[i]] == 'object') {
                        r += '<b>' + vs[i] + '</b> = ' + ObjectToStringEx(runstate.variables[vs[i]], 2) + '<br>';
                    } else {
                        r += '<b>' + vs[i] + '</b> = ' + EscapeHtml(script_toString(runstate.variables[vs[i]])) + '<br>';
                    }
                }
            }
            QH('variables', r);

            // Update state
            r = "Arrêté, aucun script";
            if (runstate && runstate != null) { r = script_states[runstate.state]; if (runstate.state > 0) r += ', ' + runstate.ip + ' : ' + script_decompile(runstate.script, runstate.ip); }
            if (r.length > 50) { r = r.substring(0, 50) + "..."; }
            QH('EditScriptStatus', r);
        }

        // Return a string from any input, if the input is an object, stringify it.
        function script_toString(x) { if (typeof x == 'object') return JSON.stringify(x); return x; }

        // ###BEGIN###{FileSaver}
        // Save a script to disk, start by showing a dialog box to prompt to the filename.
        function script_saveScript(e) {
            if (xxdialogMode || scriptstate) return;
            if (e && (e.shiftKey == true)) {
                // Save as script block
                setDialogMode(11, "Bloc de script", 1, null, '<br><textarea id=scriptSaveScriptJsonBlock style=width:100%;height:200px;resize:vertical />');
                QH('scriptSaveScriptJsonBlock', script_fConvertScriptToJsonBlock(Q('scriptarea').value));
            } else {
                // Save as .mescript file
                // ###BEGIN###{!Mode-NodeWebkit}
                setDialogMode(11, "Save Script", 3, script_saveScriptOk, '<br><input id=scriptsavename style=width:100% value=test.mescript >');
                // ###END###{!Mode-NodeWebkit}
                // ###BEGIN###{Mode-NodeWebkit}
                var chooser = document.createElement('input');
                chooser.setAttribute('type', "fichier")
                chooser.setAttribute('nwsaveas', "script.mescript");
                chooser.addEventListener('change', function() {
                    require('fs').writeFile(this.value, JSON.stringify({
                        'scriptText': Q('scriptarea').value,
                        'mescript': btoa(script_compile(Q('scriptarea').value)),
                        'blocks': script_StartingBuildingBlocks,
                        'scriptBlocks': script_BlockScript
                    }, null, '  ').replace(/\n/g, '\r\n'), function () { });
                }, false);
                chooser.click();
                // ###END###{Mode-NodeWebkit}
            }
        }

        // Once the filename is selected, save the file.
        function script_saveScriptOk() {
            if (xxdialogMode) return;
            var x = JSON.stringify({
                'scriptText': Q('scriptarea').value,
                'mescript': btoa(script_compile(Q('scriptarea').value)),
                'blocks': script_StartingBuildingBlocks,
                'scriptBlocks': script_BlockScript
            }, null, '  ');
            saveAs(data2blob(x), Q('scriptsavename').value);
        }
        // ###END###{FileSaver}

// ###END###{Scripting-Editor}

// ###BEGIN###{CertificateManager}

        //
        // Certificate Manager
        //

        /*
        function issueCertButtonOk() {
            var certopen = getInputElement('certopen');
            var files = xxDragDropCertFiles;
            if (certopen) files = certopen.files;
            if (files && files.length == 1) {
                // Issue a certificate using this file
                var reader = new FileReader();
                reader.onload = issueCertButtonOk2;
                reader.readAsBinaryString(files[0]);
            } else {
                // Issue a certificate using a dummy CA
                issueCertButtonOk3(null);
            }
        }
        */

        var certificateStore = [];
        var currentCertificate = null;

        function cert_updateCertificateList() {
            var x = '', certcount = 0;
            if (currentCertificate == null && certificateStore.length > 0) { currentCertificate = certificateStore[0]; }
            certificateStore.sort(function (a, b) { var aa = a.cert.subject.getField('CN').value; var bb = b.cert.subject.getField('CN').value; if (aa > bb) { return 1; } if (aa < bb) { return -1; } return 0; });
            for (var y in certificateStore) {
                try {
                    var certificate = certificateStore[y], name = certificate.cert.subject.getField('CN').value, extra = [];
                    if (certificate['tlsauth']) { extra.push('<span title="' + "Ce certificat sera utilisé pour authentifier cette console auprès d'Intel AMT." + '">' + "Authentification TLS" + '</span>'); }
                    if (certificate['trusted'] == true) { extra.push('<span title="' + "Nous faisons confiance aux certificats signés par ce certificat." + '">' + "De confiance" + '</span>'); }
                    if (certificate['privateKey']) { extra.push('<span title="' + "Nous avons la clé privée de ce certificat." + '">' + "Clé privée" + '</span>'); }
                    x += '<div style=margin:4px;cursor:pointer>';
                    x += '<img src=images-commander/cert' + ((certificate['privateKey'])?'2':'1') + '.png style=vertical-align:text-top;float:left;background-color:white;height:28px height=32 width=32 />';
                    x += '<div id=LCR-' + certificate['h'] + ' class=g1 style=float:left;height:28px>&nbsp;</div><div id=RCR-' + certificate['h'] + ' class=g2 style=float:right;height:28px>&nbsp;</div><div style=height:28px ';
                    // ###BEGIN###{ContextMenus}
                    var cmenus = [];
                    cmenus.push("Vue..." + '#cert_view(' + certificate['h'] +'")');
                    if (certificate['privateKey']) { cmenus.push("Émettre un nouveau cert ..." + '#cert_issueNew(' + certificate['h'] + ')'); }
                    cmenus.push("Exporter en .cer ..." + '#cert_saveCertCer(' + certificate['h'] + ')');
                    if (certificate['privateKey']) { cmenus.push("Exporter au format .p12 ..." + '#cert_saveCertP12(' + certificate['h'] + ')'); }
                    x += ' cm=\'' + cmenus.join('|') + '\'';
                    // ###END###{ContextMenus}
                    x += ' onclick=\'cert_select(event, ' + certificate['h'] + ')\' id=CR-' + certificate['h'] + ' ondblclick=cert_view(' + certificate['h'] + ')>';
                    //x += '<input id=SC-' + certificate['h'] + ' type=checkbox style=float:left;margin-top:8px onclick=cert_onCertificateChecked()' + (certificate.checked?' checked':'') + ' />';
                    x += '<div style=float:right><span style=font-size:14px>' + extra.join(', ') + '</span>&nbsp;<input type=button value="' + "Vue..." + '" onclick=cert_view(' + certificate['h'] + ')>&nbsp;</div><div style=padding-top:2px>&nbsp;';
                    // ###BEGIN###{Look-BrandedCommander}
                    //x += '<img src=images-BrandedCommander/ComputerIcon.png style=vertical-align:text-top />&nbsp;';
                    // ###END###{Look-BrandedCommander}
                    //x += '<img src=certificate.png style=vertical-align:text-top height=28 width=24 />';
                    x += '<b style=font-size:16px>' + EscapeHtml(name) + '</b></div></div></div>';
                    certcount++;
                } catch (e) { delete certificateStore[y]; }
            }
            QV('id_certStartScreen', certcount == 0);
            QH('id_certManagerMainArea', x);
            cert_select();
        }

        function cert_view(h) {
            if (xxdialogMode) return;
            var x = '', certificate = getCertificate(h), cert = certificate.cert, commonName = cert.subject.getField('CN').value;
            var fingerprint = '', fingerprint2 = forge.md.sha1.create().update(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()).digest().toHex().toUpperCase();
            for (i = 0; i < fingerprint2.length; i++) { if ((i != 0) && (i % 2 == 0)) { fingerprint += ':'; } fingerprint += fingerprint2.substring(i, i + 1); }
            x += '<img src=images-commander/cert' + ((certificate['privateKey']) ? '2' : '1') + '.png style=vertical-align:text-top;float:right;height:28px height=32 width=32 />';
            x += '<input id=certTrustedCheck type=checkbox>' + "Ceci est un certificat de confiance" + '<br>';
            var extKeyUsage = null;
            for (var i in certificate.cert.extensions) { if (certificate.cert.extensions[i].id == '2.5.29.37') { extKeyUsage = certificate.cert.extensions[i]; } }
            if ((certificate['privateKey']) && (extKeyUsage != null) && (extKeyUsage['2.16.840.1.113741.1.2.1'] == true)) { x += '<div><input id=certMutualAuth type=checkbox>' + "Utiliser pour l'authentification de la console TLS" + '<br></div>'; }
            x += '<br>';
            // ###BEGIN###{FileSaver}
            var y = atob(certificate['certbin']).length + " octets," + '<a style=cursor:pointer;color:blue onclick=cert_saveCertCer(' + h + ',1)>' + NoBreak("Enregistrer .cer") + '</a>';
            if (certificate['privateKey']) { y += ', <a style=cursor:pointer;color:blue onclick=cert_saveCertP12(' + h + ')>' + NoBreak("Enregistrer .p12") + '</a>'; }
            y += ', <a style=cursor:pointer;color:blue onclick=cert_saveCertCer(' + h + ',2)>' + NoBreak("Enregistrer .pem") + '</a>';
            x += addHtmlValueNoTitle("Certificat", y);
            // ###END###{FileSaver}
            // ###BEGIN###{!FileSaver}
            //x += addHtmlValueNoTitle("Certificate", c.X509Certificate.length + " bytes");
            // ###END###{!FileSaver}
            // Decode certificate usages
            y = [];
            if (extKeyUsage != null) {
                if (extKeyUsage.clientAuth == true) { y.push(NoBreak("Client TLS")); }
                if (extKeyUsage.codeSigning == true) { y.push(NoBreak("Signature du code")); }
                if (extKeyUsage.emailProtection == true) { y.push("Email"); }
                if (extKeyUsage.serverAuth == true) { y.push(NoBreak("Serveur TLS")); }
                if (extKeyUsage['2.16.840.1.113741.1.2.1'] == true) { y.push(NoBreak("Console Intel&reg; AMT")); }
                if (extKeyUsage['2.16.840.1.113741.1.2.2'] == true) { y.push(NoBreak("Agent Intel&reg; AMT")); }
                if (extKeyUsage['2.16.840.1.113741.1.2.3'] == true) { y.push(NoBreak("Activation Intel&reg; AMT")); }
                if (extKeyUsage.timeStamping == true) { y.push(NoBreak("Horodatage")); }
                if (y.length > 0) { x += addHtmlValueNoTitle("Utilisation du certificat", y.join(', ') + '.') + '<br clear=all />'; }
            }
            x += '<br><div style=\"border-bottom:1px solid gray\"><i>' + "Objet du certificat" + '</i></div><br>';
            for (var i in xxCertSubjectNames) { var a = cert.subject.getField(i); if (a) { x += addHtmlValue(xxCertSubjectNames[i], EscapeHtml(a.value)); } }
            x += addHtmlValueNoTitle("Empreinte digitale", fingerprint.substring(0,29) + '<br />' + fingerprint.substring(30));
            x += '<br><div style="border-bottom:1px solid gray"><i>' + "Certificat d'émetteur" + '</i></div><br>';
            for (var i in xxCertSubjectNames) { var a = cert.issuer.getField(i); if (a) { x += addHtmlValue(xxCertSubjectNames[i], EscapeHtml(a.value)); } }
            setDialogMode(11, "Certificat -" + EscapeHtml(commonName), 5, cert_viewex, x, certificate);
            Q('certTrustedCheck').checked = (certificate['trusted'] == true);
            if (certificate['privateKey'] && Q('certMutualAuth')) { Q('certMutualAuth').checked = (certificate['tlsauth'] == true); }
        }

        function cert_saveCertCer(h,type) {
            var certificate = getCertificate(h), cert = certificate.cert, commonName = cert.subject.getField('CN').value;
            // ###BEGIN###{!Mode-NodeWebkit}
            //saveAs(data2blob(xxCertificates[h].X509Certificate), xxCertificates[h].XSubject['CN'] + '.cer');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            if (type == 1) { // .cer format
                chooser.setAttribute('nwsaveas', commonName + '.cer');
                chooser.addEventListener('change', function () { require('fs').writeFile(this.value, certificate['certbin'], 'base64', function () { }); }, false);
            } else if (type == 2) { // .pem format
                chooser.setAttribute('nwsaveas', commonName + '.pem');
                chooser.addEventListener('change', function () {
                    var ptr = 0, xcert = '';
                    // Write the public certificate
                    while (ptr < certificate['certbin'].length) { xcert += certificate['certbin'].substring(ptr, ptr + Math.min(certificate['certbin'].length - ptr, 64)) + '\r\n'; ptr += 64; }
                    xcert = '-----BEGIN CERTIFICATE-----\r\n' + xcert + '-----END CERTIFICATE-----\r\n';
                    if (certificate['privateKeyBin']) { xcert += '\r\n' + certificate['privateKeyBin']; } // Write the private key
                    require('fs').writeFile(this.value, xcert, function () { });
                }, false);
            }
            chooser.click();
            setDialogMode(0);
            // ###END###{Mode-NodeWebkit}
        }

        function cert_saveCertP12(h) {
            // Prompt to the PKCS12 password
            var x = "Saisissez un mot de passe de clé privée de certificat." + '<br/><br/><div style=height:26px><input id=idx_filepass1 type=password onkeyup=cert_saveCertP12Update() style=float:right;width:200px><div>' + "Mot de passe" + '</div></div><div style=height:26px><input id=idx_filepass2 type=password onkeyup=cert_saveCertP12Update() style=float:right;width:200px><div>' + "Mot de passe" + '</div></div>';
            setDialogMode(11, "Mot de passe du certificat", 3, cert_saveCertP12b, x, h);
            cert_saveCertP12Update();
        }

        function cert_saveCertP12Update() {
            QE('idx_dlgOkButton', (Q('idx_filepass1').value == Q('idx_filepass2').value) && (Q('idx_filepass1').value.length > 0));
        }

        function cert_saveCertP12b(b, h) {
            var certificate = getCertificate(h), cert = certificate.cert, commonName = cert.subject.getField('CN').value, pass = Q('idx_filepass1').value;
            // ###BEGIN###{!Mode-NodeWebkit}
            //saveAs(data2blob(xxCertificates[h].X509Certificate), xxCertificates[h].XSubject['CN'] + '.cer');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', commonName + '.p12');
            chooser.addEventListener('change', function() {
                require('fs').writeFile(this.value, forge.util.encode64(forge.asn1.toDer(forge.pkcs12.toPkcs12Asn1(certificate['privateKey'], certificate['cert'], pass)).getBytes()), 'base64', function () { });
            }, false);
            chooser.click();
            setDialogMode(0);
            // ###END###{Mode-NodeWebkit}
        }

        function cert_viewex(b, certificate) {
            if (b == 2) {
                cert_removeCertificateEx(certificate['h']);
            } else {
                var update = 0;
                if (certificate['trusted'] != Q('certTrustedCheck').checked) { certificate['trusted'] = Q('certTrustedCheck').checked; update = 1; }
                if ((certificate['privateKey']) && Q('certMutualAuth') && (certificate['tlsauth'] != Q('certMutualAuth').checked)) {
                    for (var y in certificateStore) { certificateStore[y]['tlsauth'] = false; }
                    certificate['tlsauth'] = Q('certMutualAuth').checked;
                    update = 1;
                }
                if (update == 1) { cert_updateCertificateList(); cert_saveCertificates(); }
            }
        }

        function cert_removeCertificateEx(h) {
            cert_deleteCertificatesEx(2, [ getCertificate(h) ]);
        }

        function cert_select(e, h) {
            if (h) { currentCertificate = getCertificate(h); /*updateComputerDetails();*/ }
            for (var y in certificateStore) {
                var certificate = certificateStore[y];
                var sel = (currentCertificate != null && certificate['h'] == currentCertificate['h']);
                QS('CR-' + certificate['h'])['background-color'] = sel ? '#a0a0a0' : '#c9c9c9';
                Q('LCR-' + certificate['h']).classList.remove('g1');
                Q('LCR-' + certificate['h']).classList.remove('g1s');
                Q('RCR-' + certificate['h']).classList.remove('g2');
                Q('RCR-' + certificate['h']).classList.remove('g2s');
                Q('LCR-' + certificate['h']).classList.add(sel ? 'g1s' : 'g1');
                Q('RCR-' + certificate['h']).classList.add(sel ? 'g2s' : 'g2');
            }
            QE('IssueCertButton', (currentCertificate != null) && (currentCertificate['privateKey']));
        }

        function getCertificate(h) { for (var i in certificateStore) { if (certificateStore[i]['h'] == h) return certificateStore[i]; } return null; }
        function getCertificateWithKeyCount(h) { for (var i in certificateStore) { var c = 0; if (certificateStore[i]['privateKey']) { c++; } } return c; }
        function getTlsAuthCertificate() { for (var i in certificateStore) { if (certificateStore[i]['tlsauth'] == true) return certificateStore[i]; } return null; }

        function cert_onCertificateChecked() {
            for (var y in certificateStore) { certificateStore[y].checked = Q('SC-' + certificateStore[y]['h']).checked; }
        }

        function cert_deleteCertificates() {
            if (xxdialogMode) return;
            // Figure out how many certificates are selected.
            var clist = [];
            for (var y in certificateStore) { if (certificateStore[y].checked == true) { clist.push(certificateStore[y]); } }
            if (clist.length == 0) { clist.push(currentCertificate); }
            if (clist.length == 1) {
                setDialogMode(11, "Supprimer les certificats", 3, cert_deleteCertificatesEx, '<br>' + "Supprimer 1 certificat?", clist);
            } else {
                setDialogMode(11, "Supprimer les certificats", 3, cert_deleteCertificatesEx, '<br>' + format("Supprimer {0} certificats?", clist.length), clist);
            }
        }

        function cert_deleteCertificatesEx(button, clist) {
            for (var i in clist) {
                var handleToDelete = clist[i]['h'];
                if ((currentCertificate != null) && (currentCertificate['h'] == handleToDelete)) { currentCertificate = null; }
                for (x = 0; x < certificateStore.length; x++) { if (certificateStore[x]['h'] == handleToDelete) { certificateStore.splice(x, 1); } }
            }
            cert_saveCertificates();
            cert_updateCertificateList();
            //updateComputerDetails();
        }

        function cert_loadCertificates() {
            // ###BEGIN###{Mode-NodeWebkit}
            var ctext = null;
            try { ctext = localStorage.getItem('certificates'); } catch (ex) { }
            if (ctext) {
                try { computerlist = JSON.parse(ctext); } catch (e) {
                    if (ctext.length > 512) { // Add trivial security, not intended to be real security. This just avoids storing data in plain text, but it's almost the same.
                        var crypto = require('crypto'), k = ctext.substring(0, 512), crypted = ctext.substring(512), decipher = crypto.createDecipher('aes-256-ctr', k), dec = decipher.update(crypted, 'hex', 'utf8');
                        dec += decipher.final('utf8');
                        var certificateStore2 = JSON.parse(dec);
                        if (Array.isArray(certificateStore2) == false) { certificateStore2 = []; }
                        for (var i in certificateStore2) {
                            try {
                                certificateStore2[i].checked = false;
                                if (certificateStore2[i]['certbin']) { certificateStore2[i]['cert'] = forge.pki.certificateFromAsn1(forge.asn1.fromDer(atob(certificateStore2[i]['certbin']))); }
                                if (certificateStore2[i]['privateKeyBin']) { certificateStore2[i]['privateKey'] = forge.pki.privateKeyFromPem(certificateStore2[i]['privateKeyBin']); }
                            } catch (e) { delete certificateStore2[i]; }
                        }
                        certificateStore = [];
                        for (var i in certificateStore2) { if (typeof certificateStore2[i] == 'object') certificateStore.push(certificateStore2[i]); }
                    }
                }
            }
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            //var ctext = null;
            //try { ctext = localStorage.getItem('computers'); } catch (ex) { }
            //if (ctext) { computerlist = JSON.parse(ctext); }
            // ###END###{!Mode-NodeWebkit}
            cert_updateCertificateList();
        }

        function cert_saveCertificates() {
            // ###BEGIN###{Mode-NodeWebkit}
            const crypto = require('crypto'); 
            crypto.randomBytes(256, function(err, buf) {
                if (err) throw err; // Add trivial security, not intended to be real security. This just avoids storing data in plain text, but it's almost the same.
                var k = buf.toString('hex'), cipher = crypto.createCipher('aes-256-ctr', k), crypted = cipher.update(JSON.stringify(certificateStore), 'utf8', 'hex');
                crypted += cipher.final('hex');
                try { localStorage.setItem('certificates', k + crypted); } catch (ex) { }
            });
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            //try { localStorage.setItem('computers', JSON.stringify(computerlist)); } catch (ex) { }
            // ###END###{!Mode-NodeWebkit}
        }

        function cert_createNew() {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certcn style=float:right;width:230px><div style=padding-top:4px>' + "Nom commun" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certo style=float:right;width:230px><div style=padding-top:4px>' + "Organisation" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certst style=float:right;width:230px><div style=padding-top:4px>' + "État / Province" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certc style=float:right;width:230px><div style=padding-top:4px>' + "Pays" + '</div></div>';
            setDialogMode(11, "Créer un certificat racine", 3, cert_createNewEx, x);
            cert_createNew_Update();
        }

        function cert_createNew_Update() {
            x = (getInputElement('certcn').value != '' && getInputElement('certo').value != '' && getInputElement('certst').value != '' && getInputElement('certc').value != '');
            QE('idx_dlgOkButton', x);
        }

        // --- Extended Key Usage OID's ---
        // 1.3.6.1.5.5.7.3.1            = TLS Server certificate
        // 1.3.6.1.5.5.7.3.2            = TLS Client certificate
        // 2.16.840.1.113741.1.2.1      = Intel AMT Remote Console
        // 2.16.840.1.113741.1.2.2      = Intel AMT Local Console
        // 2.16.840.1.113741.1.2.3      = Intel AMT Client Setup Certificate (Zero-Touch)

        function cert_createNewEx(b, rootCert) {
            // Generate a keypair and create an X.509v3 certificate
            var keys = forge.pki.rsa.generateKeyPair(2048);
            var cert = forge.pki.createCertificate();
            cert.publicKey = keys.publicKey;
            cert.serialNumber = '' + Math.floor((Math.random() * 100000) + 1);
            cert.validity.notBefore = new Date(2018, 0, 1);
            //cert.validity.notBefore.setFullYear(cert.validity.notBefore.getFullYear() - 1); // Create a certificate that is valid one year before, to make sure out-of-sync clocks don't reject this cert.
            cert.validity.notAfter = new Date(2049, 11, 31);
            //cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 20);
            var attrs = [
                { name: 'commonName', value: Q('certcn').value },
                { name: 'countryName', value: Q('certc').value },
                { shortName: 'ST', value: Q('certst').value },
                { name: 'organizationName', value: Q('certo').value }
            ];
            cert.setSubject(attrs);

            if (rootCert) {
                // Use root attributes
                cert.setIssuer(rootCert['cert'].subject.attributes);
            } else {
                // Use our own attributes
                cert.setIssuer(attrs);
            }

            if (rootCert == undefined) {
                // Create a root certificate
                cert.setExtensions([{
                    name: 'basicConstraints',
                    cA: true
                }, {
                    name: 'nsCertType',
                    sslCA: true,
                    emailCA: true,
                    objCA: true
                }, {
                    name: 'subjectKeyIdentifier'
                }]);
            } else {
                // Figure out the extended key usages
                var extKeyUsage = { name: 'extKeyUsage' }
                if (Q('d11_cu1').checked) { extKeyUsage['2.16.840.1.113741.1.2.1'] = true; extKeyUsage.clientAuth = true; }
                if (Q('d11_cu2').checked) { extKeyUsage['2.16.840.1.113741.1.2.2'] = true; extKeyUsage.clientAuth = true; }
                if (Q('d11_cu3').checked) { extKeyUsage['2.16.840.1.113741.1.2.3'] = true; extKeyUsage.clientAuth = true; }
                if (Q('d11_cu4').checked) { extKeyUsage.serverAuth = true; }
                if (Q('d11_cu5').checked) { extKeyUsage.clientAuth = true; }
                if (Q('d11_cu6').checked) { extKeyUsage.emailProtection = true; }
                if (Q('d11_cu7').checked) { extKeyUsage.codeSigning = true; }
                if (Q('d11_cu8').checked) { extKeyUsage.timeStamping = true; }

                // Create a leaf certificate
                cert.setExtensions([{
                    name: 'basicConstraints'
                }, {
                    name: 'keyUsage',
                    keyCertSign: true,
                    digitalSignature: true,
                    nonRepudiation: true,
                    keyEncipherment: true,
                    dataEncipherment: true
                }, extKeyUsage, {
                    name: 'nsCertType',
                    client: Q('d11_cu5').checked,
                    server: Q('d11_cu4').checked,
                    email: Q('d11_cu6').checked,
                    objsign: Q('d11_cu7').checked,
                }, {
                    name: 'subjectKeyIdentifier'
                } ]);
            }

            // Self-sign certificate
            if (rootCert) {
                cert.sign(rootCert['privateKey'], forge.md.sha256.create());
            } else {
                cert.sign(keys.privateKey, forge.md.sha256.create());
            }

            // Save the certificate in the store
            certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(hex2rstr(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).toHex())), 'privateKey': keys.privateKey, 'privateKeyBin': forge.pki.privateKeyToPem(keys.privateKey), 'checked': false });
            cert_saveCertificates();
            cert_updateCertificateList();
        }

        function cert_issueNew() {
            if (xxdialogMode) return;
            var x = '';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certcn style=float:right;width:230px><div style=padding-top:4px>' + "Nom commun" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certo style=float:right;width:230px><div style=padding-top:4px>' + "Organisation" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certst style=float:right;width:230px><div style=padding-top:4px>' + "État / Province" + '</div></div>';
            x += '<div style=height:26px;margin-top:4px><input onkeyup=cert_createNew_Update() id=certc style=float:right;width:230px><div style=padding-top:4px>' + "Pays" + '</div></div>';
            x += '<div>Certificate Usages</div><ul style="list-style-type:none;height:100px;overflow:auto;width:100%;border: 1px solid #000;background-color:white;overflow-x:hidden;margin:0;padding:0">';
            x += '<li><label><input type=checkbox id=d11_cu1>' + "Console Intel&reg; AMT" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu2>' + "Agent Intel&reg; AMT" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu3>' + "Activation Intel&reg; AMT" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu4>' + "Serveur TLS (HTTPS)" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu5>' + "Client TLS (HTTPS)" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu6>' + "Protection des e-mails" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu7>' + "Signature du code" + '</label></li>';
            x += '<li><label><input type=checkbox id=d11_cu8>' + "Horodatage" + '</label></li>';
            x += '</ul>';
            setDialogMode(11, format("Délivrer un certificat signé par {0}", currentCertificate.cert.subject.getField('CN').value), 3, cert_createNewEx, x, currentCertificate);
            cert_issueNew_Update();
        }

        function cert_issueNew_Update() {
            x = (getInputElement('certcn').value != '' && getInputElement('certo').value != '' && getInputElement('certst').value != '' && getInputElement('certc').value != '');
            QE('idx_dlgOkButton', x);
        }

        function cert_importCert() {
            if (xxdialogMode) return;
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = Q('certOpenFile');
            if (chooser.getAttribute('eventset') != 1) {
                chooser.setAttribute('eventset', '1');
                chooser.addEventListener('change', cert_importCertOk, false);
            }
            chooser.value = null;
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }

        function cert_importCertOk2(e) {
            haltEvent(e);
            if (e.dataTransfer.files.length == 1) {
                var reader = new FileReader();
                if (e.dataTransfer.files[0].name.toLowerCase().endsWith('.p12') || e.dataTransfer.files[0].name.toLowerCase().endsWith('.pfx')) {
                    reader.onload = cert_importCertOkP12;
                } else {
                    reader.onload = cert_importCertOkCER;
                }
                reader.readAsBinaryString(e.dataTransfer.files[0]);
            }
        }

        function cert_importCertOk() {
            var x = Q('certOpenFile');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            if (x.files[0].name.toLowerCase().endsWith('.p12') || x.files[0].name.toLowerCase().endsWith('.pfx')) { reader.onload = cert_importCertOkP12; } else { reader.onload = cert_importCertOkCER; }
            reader.readAsBinaryString(x.files[0]);
        }

        function cert_importCertOkP12(file) {
            // Prompt to the PKCS12 password
            var x = "Le fichier de certificat sélectionné nécessite un mot de passe." + '<br/><br/><div style=height:26px><input id=idx_filepass type=password style=float:right;width:200px><div>' + "Mot de passe" + '</div></div>';
            setDialogMode(11, "Mot de passe du certificat", 3, cert_importCertOkP12b, x, file);
        }

        function cert_importCertOkP12b(button, file) {
            // Try to decode the PKCS12 file
            var p12;
            try { p12 = forge.pkcs12.pkcs12FromAsn1(forge.asn1.fromDer(file.target.result), Q('idx_filepass').value); } catch (e) { setDialogMode(11, "Fichier de certificat", 1, function() {}, "Mot de passe de certificat non valide ou impossible de décoder le fichier."); return; }
            var bags1 = p12.getBags({bagType: forge.pki.oids.certBag});
            var cert = bags1[forge.pki.oids.certBag][0].cert;
            var bags2 = p12.getBags({bagType: '1.2.840.113549.1.12.10.1.2'})
            var key = bags2['1.2.840.113549.1.12.10.1.2'][0].key;
            certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(hex2rstr(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).toHex())), 'privateKey': key, 'privateKeyBin': forge.pki.privateKeyToPem(key), 'checked': false });
            cert_saveCertificates();
            cert_updateCertificateList();
        }

        function cert_importCertOkCER(file) {
            var cert, str = file.target.result;
            var pemcert = cert_getMiddleString(str, '-----BEGIN CERTIFICATE-----', '-----END CERTIFICATE-----');
            var pemkey = cert_getMiddleString(str, '-----BEGIN PRIVATE KEY-----', '-----END PRIVATE KEY-----');
            if (pemkey == null) { pemkey = cert_getMiddleString(str, '-----BEGIN RSA PRIVATE KEY-----', '-----END RSA PRIVATE KEY-----'); }
            if (pemcert != null) {
                // Try to decode the .PEM file
                try { cert = forge.pki.certificateFromPem(pemcert); } catch (e) { setDialogMode(11, "Fichier de certificat", 1, function () { }, "Impossible de décoder le fichier PEM."); return; }
                if (pemkey == null) {
                    // Public key only
                    certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()), 'checked': false });
                } else {
                    // Public and private key
                    var privatekey;
                    try { privatekey = forge.pki.privateKeyFromPem(pemkey); } catch (e) { setDialogMode(11, "Fichier de certificat", 1, function () { }, "Impossible de décoder la clé privée PEM."); return; }
                    certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()), 'privateKey': privatekey, 'privateKeyBin': forge.pki.privateKeyToPem(privatekey), 'checked': false });
                }
            } else {
                // Try to decode the .CER file, public key only
                try { cert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(str)); } catch (e) { setDialogMode(11, "Fichier de certificat", 1, function () { }, "Impossible de décoder le fichier de certificat."); return; }
                certificateStore.push({ 'h': Math.random(), 'cert': cert, 'certbin': btoa(file.target.result), 'checked': false });
            }
            cert_saveCertificates();
            cert_updateCertificateList();
        }

        function cert_getMiddleString(str, start, end) { var a = str.indexOf(start), b = str.indexOf(end); if ((a == -1) || (b == -1) || (b < a)) return null; return str.substring(a, b + end.length); }

// ###END###{CertificateManager}
        
// ###BEGIN###{USBSetup}

        //
        // USB SETUP.BIN
        //

        function usb_newSetupBin() {
            if (xxdialogMode) return;
            idx_d14version.value = 4;
            idx_d14consume.value = 1;
            setDialogMode(14, "Créer un nouveau fichier Setup.bin", 3, usb_newSetupBinOk);
        }

        function usb_newSetupBinOk(r) {
            if (r == 1) { setupbin = AmtSetupBinCreate(idx_d14version.value, idx_d14consume.value); } // OK Button
            usb_displaySetupBin();
        }

        function usb_openSetupBin() {
            if (xxdialogMode) return;
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('accept', '.bin')
            chooser.addEventListener('change', function() {
                setupbin = AmtSetupBinDecode(require('fs').readFileSync(this.value, 'binary'));
                if (!setupbin) { messagebox("Fichier ouvert", "Fichier setup.bin invalide ou corrompu. Incapable d'ouvrir."); } else { usb_displaySetupBin(); }
            }, false);
            chooser.value = null;
            chooser.click();
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{!Mode-NodeWebkit}
            setDialogMode(15, "Open Setup.bin file", 3, usb_openSetupBinOk);
            // ###END###{!Mode-NodeWebkit}
        }

        function usb_openSetupBinOk() {
            var x = Q('d15setupbinfile');
            if (x.files.length != 1) return;
            var reader = new FileReader();
            reader.onload = usb_onSetupBinRead;
            reader.readAsBinaryString(x.files[0]);
        }

        // ###BEGIN###{FileSaver}
        function usb_saveSetupBin() {
            if (xxdialogMode || !setupbin) return;
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(AmtSetupBinEncode(setupbin)), 'setup.bin');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', 'setup.bin');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, AmtSetupBinEncode(setupbin), 'binary', function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        function usb_onSetupBinRead(file) {
            setupbin = AmtSetupBinDecode(file.target.result);
            if (!setupbin) { messagebox("Fichier ouvert", "Fichier setup.bin invalide ou corrompu. Incapable d'ouvrir."); } else { usb_displaySetupBin(); }
        }

        function usb_displaySetupBin() {
            QV('id_StartupScreen', !setupbin);
            // ###BEGIN###{FileSaver}
            QV('id_saveSetupBin', setupbin);
            // ###END###{FileSaver}
            if (!setupbin) { return QH('id_SetupBinArea', ''); }
            
            // Update record count
            var consumed = 0;
            for (var i in setupbin.records) { if ((setupbin.records[i].flags & 1) == 0) { consumed++; } }
            setupbin.dataRecordsConsumed = consumed;

            // Main Header            
            var x = '<table onclick=usb_editheader(event) class="log1 us" cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px;cursor:pointer><tr><td><p><td>';
            x += '<tr><td class=r2 style=padding-left:15px>';
            x += '<div style=float:right;margin-right:12px onclick=usb_addRecordSetupBin()><a><u title=\'' + "Ajouter un nouvel enregistrement" + '\'>' + "Ajouter un enregistrement" + '</u></a></div>';
            x += '<div><strong>' + format("Version du fichier Intel&reg; AMT Setup.bin {0}. {1}", setupbin.majorVersion, + setupbin.minorVersion) + '</strong>.</div>';
            x += (((setupbin.flags & 1) == 0) ? 'Records will be consumed.' : 'Records will not be consumed.');
            x += '<br>' + format("Enregistrements: {0}, consommés: {1}", setupbin.records.length, setupbin.dataRecordsConsumed)+ '<br>';
            x += '<tr style=height:4px></table>';

            // Display each record
            for (var i in setupbin.records) {
                var rec = setupbin.records[i];
                x += '<div style=height:4px></div><table class="log1 us" cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td><p><td><tr><td class=r2 style=padding-left:15px;cursor:pointer>';
                x += '<div style=float:right;margin-right:12px onclick="usb_addvariable(event,' + i + ')"><a><u title="' + "Ajouter une nouvelle variable" + '">' + "Ajouter une variable" + '</u></a></div>';
                x += '<div onclick=\'usb_editrecord(event, ' + i + ')\'>' + "Record #" + '<strong>' + (+i + 1) + '</strong>. ' + "Ce record est: " + '<strong>' + ((rec.flags & 1) ? "Valide" : "Consommé") + ((rec.flags & 2) ? ", Brouillé" : '') + '</strong></div>';

                // Display each variable
                for (var j in rec.variables) {
                    var v = rec.variables[j], val = v.value;
                    if (AmtSetupBinVarIds[v.moduleid][v.varid][2] && AmtSetupBinVarIds[v.moduleid][v.varid][2][val]) { val = AmtSetupBinVarIds[v.moduleid][v.varid][2][val]; }
                    if (v.moduleid == 2 && v.varid == 8) {
                        var hashtype = val.charCodeAt(0);
                        if (hashtype >= 0 && hashtype <= 3) {
                            var hashsize = [20, 32, 48][hashtype - 1];
                            var hash = rstr2hex(val.substring(1, hashsize + 1));
                            var hashnamesize = val.charCodeAt(1 + hashsize);
                            var hashname = val.substring(2 + hashsize, 2 + hashsize + hashnamesize)
                            val = ['SHA1', 'SHA256', 'SHA384'][hashtype - 1] + ', ' + hashname + ', ' + hash;
                        }
                    }
                    if (v.moduleid == 2 && v.varid == 17) {
                        val = val.charCodeAt(3) + '.' + val.charCodeAt(2) + '.' + val.charCodeAt(1) + '.' + val.charCodeAt(0);
                    }
                    x += '<div style=margin-right:12px><table onclick=\'usb_editvariable(event,' + i + ',' + j + ')\' class=\'itemBar us\' cellpadding=0 cellspacing=0 style=width:100%;border-radius:4px;margin-top:2px;margin-bottom:2px;padding:0><tr><td><p style=float:right;margin-right:8px><b>' + val + '</b><p>' + v['desc'] + '<tr style=height:4px></table></div>';
                }

                x += '<tr style=height:4px></table>';
            }

            QH('id_SetupBinArea', x);
        }

        function usb_addRecordSetupBin() {
            if (xxdialogMode) return;
            d13valid.checked = 1;
            d13scramble.checked = 0;
            QV('d13ScrambledRecordSpan', setupbin.majorVersion > 3);
            setDialogMode(13, "Nouvel enregistrement #", 3, usb_addRecordSetupBinOk);
        }

        function usb_addRecordSetupBinOk() {
            var r = {};
            r.typeIdentifier = 1;
            r.flags = (d13valid.checked ? 1 : 0) + (d13scramble.checked ? 2 : 0);
            r.chunkCount = 0;
            r.headerByteCount = 0;
            r.number = 0;
            r.variables = [];
            setupbin.records.push(r);
            usb_displaySetupBin();
        }

        function usb_editheader(e) {
            if (xxdialogMode) return;
            haltEvent(e);
            idx_d14version.value = setupbin.majorVersion;
            idx_d14consume.value = (setupbin.flags & 1);
            setDialogMode(14, "Modifier l'en-tête", 7, usb_editheaderok);
        }

        function usb_editheaderok(r) {
            if (r == 2) {
                delete setupbin;
            } else {
                setupbin.majorVersion = idx_d14version.value;
                setupbin.flags = idx_d14consume.value;
            }
            usb_displaySetupBin();
        }

        function usb_editrecord(e, i) {
            if (xxdialogMode) return;
            selectedRecord = i;
            selectedVariable = -1;
            haltEvent(e);
            d13valid.checked = (setupbin.records[selectedRecord].flags & 1);
            d13scramble.checked = (setupbin.records[selectedRecord].flags & 2);
            QV('d13ScrambledRecordSpan', setupbin.majorVersion > 3);
            setDialogMode(13, format("Modifier l'enregistrement # {0}", (i + 1)), 7, usb_editrecordok);
        }

        function usb_editrecordok(r) {
            if (r == 1) { setupbin.records[selectedRecord].flags = (d13valid.checked ? 1 : 0) + (d13scramble.checked ? 2 : 0); } // Edit Record
            if (r == 2) { setupbin.records.splice(selectedRecord, 1); } // Delete Record
            usb_displaySetupBin();
        }

        function usb_editvariable(e, i, j) {
            if (xxdialogMode) return;
            selectedRecord = i;
            selectedVariable = j;
            var modid = setupbin.records[i].variables[j].moduleid;
            var varid = setupbin.records[i].variables[j].varid;
            d16type.value = modid + '-' + varid;
            d16type.disabled = true;
            usb_ond16typechange();
            QV('d16genericvalue', false);
            QV('d16customvalue', false);
            if (modid == 2 && varid == 8) {
                var x = '<div style=height:26px><select id=idx_d16valc1 style=float:right;width:260px onchange=usb_ond16checkhash()><option value=1>' + "SHA1" + '</option>';
                if (setupbin.majorVersion >= 3) { x += '<option value=2>SHA256</option><option value=3>' + "SHA384" + '</option>'; }
                x += '</select><div>' + "Type de hachage" + '</div></div>';
                x += '<div style=height:26px><input id=idx_d16valc2 style=float:right;width:260px onkeyup=usb_ond16checkhash()><div>' + "Hachage (HEX)" + '</div></div>';
                x += '<div style=height:26px><input id=idx_d16valc3 style=float:right;width:260px onkeyup=usb_ond16checkhash() maxlength=31><div>' + "Nom de hachage" + '</div></div>';
                QH('d16customvalue', x);
                QV('d16customvalue', true);
                var val = setupbin.records[i].variables[j].value;
                var hashtype = val.charCodeAt(0);
                if (hashtype >= 0 && hashtype <= 3) {
                    var hashsize = [20, 32, 48][hashtype - 1];
                    var hash = rstr2hex(val.substring(1, hashsize + 1));
                    var hashnamesize = val.charCodeAt(1 + hashsize);
                    var hashname = val.substring(2 + hashsize, 2 + hashsize + hashnamesize)
                    val = ["SHA1", "SHA256", "SHA384"][hashtype - 1] + ', ' + hashname + ', ' + hash;
                    Q('idx_d16valc1').value = hashtype;
                    Q('idx_d16valc2').value = hash;
                    Q('idx_d16valc3').value = hashname;
                }
                usb_ond16checkhash();
            } else if (modid == 2 && varid == 17) {  // Provisioning server address
                QV('d16genericvalue', true);
                var ip = setupbin.records[i].variables[j].value;
                idx_d16value1.value = idx_d16value2.value = ip.charCodeAt(3) + '.' + ip.charCodeAt(2) + '.' + ip.charCodeAt(1) + '.' + ip.charCodeAt(0);
            } else {
                QV('d16genericvalue', true);
                idx_d16value1.value = idx_d16value2.value = setupbin.records[i].variables[j].value;
            }
            haltEvent(e);
            setDialogMode(16, format("Modifier l'enregistrement # {0}, variable # {1}", (i + 1), (j + 1)), 7, usb_editvariableok);
        }

        function usb_editvariableok(r) {
            if (r == 1) { // OK
                var ids = d16type.value.split('-');
                var modid = +ids[0];
                var varid = +ids[1];
                var value = '';
                var vardescription = AmtSetupBinVarIds[modid][varid];
                if ((modid == 2) && (varid == 8)) {
                    value = String.fromCharCode(Q('idx_d16valc1').value) + hex2rstr(Q('idx_d16valc2').value) + String.fromCharCode(Q('idx_d16valc3').value.length) + Q('idx_d16valc3').value;
                } else {
                    if (vardescription[2]) { value = idx_d16value1.value; } else { value = idx_d16value2.value; }
                }
                if ((modid == 2) && (varid == 17)) {  // Provisioning server address
                    var ipSplit = value.split('.');
                    if (ipSplit.length != 4) return;
                    value = String.fromCharCode(parseInt(ipSplit[3]), parseInt(ipSplit[2]), parseInt(ipSplit[1]), parseInt(ipSplit[0]));
                }
                setupbin.records[selectedRecord].variables[selectedVariable].value = value;
            }
            if (r == 2) { setupbin.records[selectedRecord].variables.splice(selectedVariable, 1); } // Delete
            usb_displaySetupBin();
        }

        function usb_addvariable(e, i) {
            if (xxdialogMode) return;
            selectedRecord = i;
            d16type.value = '1-1';
            d16type.disabled = false;
            idx_d16value1.value = idx_d16value2.value = '';
            usb_ond16typechange();
            haltEvent(e);
            setDialogMode(16, format("Ajouter une variable à l'enregistrement # {0}", (i + 1)), 3, usb_addvariableok);
        }

        function usb_addvariableok() {
            var ids = d16type.value.split('-');
            var modid = +ids[0];
            var varid = +ids[1];
            var value = '';
            var vardescription = AmtSetupBinVarIds[modid][varid];
            if ((modid == 2) && (varid == 8)) {
                value = String.fromCharCode(Q('idx_d16valc1').value) + hex2rstr(Q('idx_d16valc2').value) + String.fromCharCode(Q('idx_d16valc3').value.length) + Q('idx_d16valc3').value;
            } else {
                if (vardescription[2]) { value = idx_d16value1.value; } else { value = idx_d16value2.value; }
            }
            if ((modid == 2) && (varid == 17)) { // Provisioning server address
                var ipSplit = value.split('.');
                if (ipSplit.length != 4) return;
                value = String.fromCharCode(parseInt(ipSplit[3]), parseInt(ipSplit[2]), parseInt(ipSplit[1]), parseInt(ipSplit[0]));
            }

            // Create a new variable
            var v = {};
            v.moduleid = modid;
            v.varid = varid;
            v.length = -1;
            v.type = AmtSetupBinVarIds[modid][varid][0];
            v.desc = AmtSetupBinVarIds[modid][varid][1];
            v.value = value;
            setupbin.records[selectedRecord].variables.push(v);

            setupbin.records[selectedRecord].variables.sort(AmtSetupBinVariableCompare); // Sort the variables
            usb_displaySetupBin();
        }

        function usb_ond16typechange() {
            var ids = d16type.value.split('-');
            var modid = +ids[0];
            var varid = +ids[1];
            var vardescription = AmtSetupBinVarIds[modid][varid];
            QV('d16genericvalue', false);
            QV('d16customvalue', false);
            if (modid == 2 && varid == 8) {
                var x = '<div style=height:26px><select id=idx_d16valc1 style=float:right;width:260px onchange=usb_ond16checkhash()><option value=1>' + "SHA1" + '</option>';
                if (setupbin.majorVersion >= 3) { x += ('<option value=2>' + "SHA256" + '</option><option value=3>' + "SHA384" + '</option>'); }
                x += '</select><div>' + "Type de hachage" + '</div></div>';
                x += '<div style=height:26px><input id=idx_d16valc2 style=float:right;width:260px onkeyup=usb_ond16checkhash()><div>' + "Hachage (HEX)" + '</div></div>';
                x += '<div style=height:26px><input id=idx_d16valc3 style=float:right;width:260px onkeyup=usb_ond16checkhash() maxlength=31><div>' + "Nom de hachage" + '</div></div>';
                QV('d16customvalue', true);
                QH('d16customvalue', x);
                usb_ond16checkhash();
            } else {
                QV('d16genericvalue', true);
                if (vardescription[2]) {
                    QV('idx_d16value1', true);
                    QV('idx_d16value2', false);
                    var options = '';
                    for (var i in vardescription[2]) { options += '<option value="' + i + '">' + vardescription[2][i] }
                    QH('idx_d16value1', options);
                } else {
                    QV('idx_d16value1', false);
                    QV('idx_d16value2', true);
                }
            }
        }

        function usb_ond16checkhash() {
            var hashtype = Q('idx_d16valc1').value;
            var hashlen = hex2rstr(Q('idx_d16valc2').value).length;
            QE('idx_dlgOkButton', (Q('idx_d16valc3').value.length > 0) && ((hashtype == 1) && (hashlen == 20)) || ((hashtype == 2) && (hashlen == 32)) || ((hashtype == 3) && (hashlen == 48)));
        }

        var usb_alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

        function usb_computeChecksum(s) {
            var A = 0;
            for (var i = 0; i < s.length; i++) A += s.charCodeAt(i);
            return usb_alphabet[A % 36];
        }

        function usb_generateRandomPid() {
            var pid = '';
            for (var i = 0; i < 7; i++) { pid += usb_alphabet[random(36)]; }
            return pid + usb_computeChecksum(pid);
        }

        function usb_generateRandomPps()
        {
            var pps = '', s;
            for (var j = 0; j < 8; j++) {
                s = '';
                for (var i = 0; i < 3; i++) s += usb_alphabet[random(36)];
                pps += s + usb_computeChecksum(s);
            }
            return pps;
        }

        // ###END###{USBSetup}

        // ###BEGIN###{SessionRecording}

        var recFile = null;
        var recFilePtr = 0;
        var recFileStartTime = 0;
        var recFileLastTime = 0;
        var recFileEndTime = 0;
        var recFileMetadata = null;
        var recFileProtocol = 0;
        var agentDesktop = null;
        var agentTerminal = null;
        var amtDesktop = null;
        var srec_playing = 0; // 0 = Stopped, 1 = Pausing, 2 = Playing
        var readState = 0;
        var waitTimer = null;
        var waitTimerArgs = null;
        var srec_deskAspectRatio = 0;
        var currentDeltaTimeTotalSec = 0;

        function readNextBlock(func) {
            if ((recFilePtr + 16) > recFile.size) { QS('srec_progressbar').width = '100%'; func(-1); } else {
                var fr = new FileReader();
                fr.onload = function () {
                    var type = ReadShort(this.result, 0);
                    var flags = ReadShort(this.result, 2);
                    var size = ReadInt(this.result, 4);
                    var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
                    if ((recFilePtr + 16 + size) > recFile.size) { QS('srec_progressbar').width = '100%'; func(-1); } else {
                        var fr2 = new FileReader();
                        fr2.onload = function () {
                            recFilePtr += (16 + size);
                            if (recFileEndTime == 0) {
                                // File pointer progress bar
                                QS('srec_progressbar').width = Math.floor(100 * (recFilePtr / recFile.size)) + '%';
                            } else {
                                // Time progress bar
                                QS('srec_progressbar').width = Math.floor(((recFileLastTime - recFileStartTime) / (recFileEndTime - recFileStartTime)) * 100) + '%';
                            }
                            func(type, flags, time, this.result);
                        };
                        fr2.readAsBinaryString(recFile.slice(recFilePtr + 16, recFilePtr + 16 + size));
                    }
                };
                fr.readAsBinaryString(recFile.slice(recFilePtr, recFilePtr + 16));
            }
        }

        function readLastBlock(func) {
            if (recFile.size < 32) { func(-1); } else {
                var fr = new FileReader();
                fr.onload = function () {
                    var type = ReadShort(this.result, 0);
                    var flags = ReadShort(this.result, 2);
                    var size = ReadInt(this.result, 4);
                    var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
                    if ((type == 3) && (size == 16) && (this.result.substring(16, 32) == 'MeshCentralMCREC')) { func(type, flags, time); } else { func(-1); }
                };
                fr.readAsBinaryString(recFile.slice(recFile.size - 32, recFile.size));
            }
        }

        function addInfo(name, value) { if (value == null) return ''; return addInfoNoEsc(name, EscapeHtml(value)); }

        function addInfoNoEsc(name, value) {
            if (value == null) return '';
            return '<span style=color:gray>' + EscapeHtml(name) + '</span>:&nbsp;<span style=font-size:20px;color:black>' + value + '</span><br/>';
        }

        function processFirstBlock(type, flags, time, data) {
            recFileProtocol = 0;
            if ((type != 1) || (flags != 0)) { cleanup(); return; }
            try { recFileMetadata = JSON.parse(data) } catch (ex) { cleanup(); return; }
            if ((recFileMetadata == null) || (recFileMetadata.magic != 'MeshCentralRelaySession') || (recFileMetadata.ver != 1)) { cleanup(); return; }
            var x = '';
            x += addInfo("Temps", recFileMetadata.time);
            if (recFileEndTime != 0) {
                var secs = Math.floor((recFileEndTime - time) / 1000);
                if (secs > 1) { x += addInfo("Durée", format("{0} secondes", secs)); } else { x += addInfo("Durée", "1 seconde"); }
            }
            x += addInfo("Nom d'utilisateur", recFileMetadata.username);
            x += addInfo("Identifiant d'utilisateur", recFileMetadata.userid);
            x += addInfo("ID de session", recFileMetadata.sessionid);
            if (recFileMetadata.ipaddr1 && recFileMetadata.ipaddr2) { x += addInfo("Adresses", format("{0} à {1}", recFileMetadata.ipaddr1, recFileMetadata.ipaddr2)); }
            x += addInfo("NodeID", recFileMetadata.nodeid);
            if (recFileMetadata.protocol) {
                var p = recFileMetadata.protocol;
                if (p == 1) { p = "Terminal MeshCentral"; }
                else if (p == 2) { p = "Bureau MeshCentral"; }
                else if (p == 100) { p = "Intel&reg; AMT WSMAN"; }
                else if (p == 101) { p = "Redirection Intel&reg; AMT"; }
                else if (p == 200) { p = "Intel&reg; AMT KVM"; }
                x += addInfoNoEsc("Protocole", p);
            }
            QV('srec_DeskParent', false);
            QV('srec_TermParent', false);
            if (recFileMetadata.protocol == 1) {
                // MeshCentral remote terminal
                recFileProtocol = 1;
                x += '<br /><br /><span style=color:gray>' + "Appuyez sur [espace] pour lire / mettre en pause." + '</span>';
                QE('srec_PlayButton', true);
                QE('srec_PauseButton', false);
                QE('srec_RestartButton', false);
                QV('srec_toggleviewmode', false);
                recFileStartTime = recFileLastTime = time;
            }
            else if (recFileMetadata.protocol == 2) {
                // MeshCentral remote desktop
                recFileProtocol = 2;
                x += '<br /><br /><span style=color:gray>' + "Appuyez sur [espace] pour lire / mettre en pause." + '</span>';
                QE('srec_PlayButton', true);
                QE('srec_PauseButton', false);
                QE('srec_RestartButton', false);
                QV('srec_toggleviewmode', true);
                recFileStartTime = recFileLastTime = time;
                agentDesktop = CreateAgentRemoteDesktop('srec_Desk');
                agentDesktop.onScreenSizeChange = srec_deskAdjust;
                agentDesktop.State = 3;
                srec_deskAdjust();
            }
            else if (recFileMetadata.protocol == 101) {
                // Intel AMT Redirection
                recFileProtocol = 101;
                x += '<br /><br /><span style=color:gray>' + "Appuyez sur [espace] pour lire / mettre en pause." + '</span>';
                QE('srec_PlayButton', true);
                QE('srec_PauseButton', false);
                QE('srec_RestartButton', false);
                QV('srec_toggleviewmode', true);
                recFileStartTime = recFileLastTime = time;
                amtDesktop = CreateAmtRemoteDesktop('srec_Desk');
                amtDesktop.onScreenSizeChange = srec_deskAdjust;
                amtDesktop.State = 3;
                amtDesktop.Start();
                srec_deskAdjust();
            } else if (recFileMetadata.protocol == 200) {
                // Intel AMT Midstream KVM
                recFileProtocol = 200;
                x += '<br /><br /><span style=color:gray>' + "Appuyez sur [espace] pour lire / mettre en pause." + '</span>';
                QE('srec_PlayButton', true);
                QE('srec_PauseButton', false);
                QE('srec_RestartButton', false);
                QV('srec_toggleviewmode', true);
                recFileStartTime = recFileLastTime = time;
                amtDesktop = CreateAmtRemoteDesktop('srec_Desk');
                amtDesktop.onScreenSizeChange = srec_deskAdjust;
                amtDesktop.State = 3;
                amtDesktop.Start();
                if (recFileMetadata.bpp) { amtDesktop.bpp = recFileMetadata.bpp; }
                if (recFileMetadata.graymode) { amtDesktop.graymode = recFileMetadata.graymode; }
                if (recFileMetadata.lowcolor) { amtDesktop.lowcolor = recFileMetadata.lowcolor; }
                amtDesktop.state = 3;
                srec_deskAdjust();
            }
            QV('srec_metadatadiv', true);
            QH('srec_metadatadiv', x);
            QH('srec_deskstatus', recFile.name);
        }

        function processBlock(type, flags, time, data) {
            if (type < 0) { srec_pause(); return; }
            var waitTime = Math.round((time - recFileLastTime) * parseFloat(Q('srec_PlaySpeed').value));
            if (waitTime < 5) {
                processBlockEx(type, flags, time, data);
            } else {
                waitTimerArgs = [type, flags, time, data]
                waitTimer = setTimeout(function () { waitTimer = null; processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]); }, waitTime);
            }
        }

        function processBlockEx(type, flags, time, data) {
            if (srec_playing == 0) return;
            var flagBinary = (flags & 1) != 0, flagUser = (flags & 2) != 0;

            // Update the clock
            var deltaTimeTotalSec = Math.floor((time - recFileStartTime) / 1000);
            if (currentDeltaTimeTotalSec != deltaTimeTotalSec) {
                currentDeltaTimeTotalSec = deltaTimeTotalSec;
                var deltaTimeHours = Math.floor(deltaTimeTotalSec / 3600);
                deltaTimeTotalSec -= (deltaTimeHours * 3600)
                var deltaTimeMinutes = Math.floor(deltaTimeTotalSec / 60);
                deltaTimeTotalSec -= (deltaTimeHours * 60)
                var deltaTimeSeconds = Math.floor(deltaTimeTotalSec);
                QH('srec_timespan', pad2(deltaTimeHours) + ':' + pad2(deltaTimeMinutes) + ':' + pad2(deltaTimeSeconds))
            }

            if ((type == 2) && flagBinary && !flagUser) {
                // Device --> User data
                if (recFileProtocol == 1) {
                    // MeshCentral Terminal
                    agentTerminal.ProcessData(data);
                } else if (recFileProtocol == 2) {
                    // MeshCentral Remote Desktop
                    agentDesktop.ProcessData(data);
                } else if (recFileProtocol == 101) {
                    // Intel AMT KVM
                    if ((readState == 0) && (rstr2hex(data).startsWith('4100000000000000'))) {
                        // We are not authenticated, KVM data starts here.
                        readState = 1;
                        if (data.length > 8) {
                            var view = new Uint8Array(data.length - 8);
                            for (var i = 8; i < data.length; i++) { view[i] = data.charCodeAt(i); }
                            amtDesktop.ProcessBinaryData(view.buffer);
                        }
                    } else if (readState == 1) {
                        var view = new Uint8Array(data.length);
                        for (var i = 0; i < data.length; i++) { view[i] = data.charCodeAt(i); }
                        amtDesktop.ProcessBinaryData(view.buffer);
                    }
                } else if (recFileProtocol == 200) {
                    // Intel AMT midstream KVM
                    var view = new Uint8Array(data.length);
                    for (var i = 0; i < data.length; i++) { view[i] = data.charCodeAt(i); }
                    amtDesktop.ProcessBinaryData(view.buffer);
                }
            } else if ((type == 2) && flagBinary && flagUser) {
                // User --> Device data
                if (recFileProtocol == 101) {
                    // Intel AMT KVM
                    if (rstr2hex(data) == '0000000008080001000700070003050200000000') { console.log('RGB8'); amtDesktop.bpp = 1; } // Switch to 1 byte per pixel, 256 colors
                    if (rstr2hex(data) == '000000000808000100FF00000000000000000000') { console.log('GRAY8'); amtDesktop.bpp = 1; obj.graymode = true; } // Switch to 1 byte per pixel, 256 grays
                    if (rstr2hex(data) == '0000000008040001000F00000000000000000000') { console.log('GRAY4'); amtDesktop.bpp = 1; obj.graymode = true; obj.lowcolor = true; } // Switch to 1 byte per pixel, 16 grays
                }
            }

            // This is a PNG screenshot of the display, load it and render it.
            if ((type == 3) && (recFileProtocol == 200)) {
                var tile = new Image();
                tile.src = 'data:image/png;base64,' + btoa(data);
                tile.onload = function () { amtDesktop.canvas.drawImage(tile, 0, 0); }
                tile.error = function () { }
            }

            recFileLastTime = time;
            if (srec_playing == 2) { readNextBlock(processBlock); }
        }

        function srec_cleanup() {
            recFile = null;
            recFilePtr = 0;
            recFileMetadata = null;
            srec_playing = 0;
            if (agentDesktop != null) { agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height); agentDesktop = null; }
            if (amtDesktop != null) { amtDesktop.canvas.clearRect(0, 0, amtDesktop.canvasid.width, amtDesktop.canvasid.height); amtDesktop = null; }
            readState = 0;
            waitTimerArgs = null;
            currentDeltaTimeTotalSec = 0;
            recFileEndTime = 0;
            agentTerminal = null;
            if (waitTimer != null) { clearTimeout(waitTimer); waitTimer = null; }
            QH('srec_deskstatus', '');
            QE('srec_PlayButton', false);
            QE('srec_PauseButton', false);
            QE('srec_RestartButton', false);
            QS('srec_progressbar').width = '0px';
            QH('srec_timespan', '00:00:00');
            QV('srec_metadatadiv', true);
            QH('srec_metadatadiv', '<div style="width:100%;text-align:center;color:gray;margin-top:26px"><span style="font-size:20px">' + "Lecteur de session enregistrée" + '</span><div style="margin:4px">' + "Faites glisser et déposez un fichier .mcrec ou cliquez sur \"Ouvrir le fichier ... \"" + '</div></div>');
            QV('srec_DeskParent', false);
            QV('srec_TermParent', false);
            QV('srec_toggleviewmode', false);
        }

        function srec_ondrop(e) {
            haltEvent(e);

            // Check if these are files we can upload, remove all folders.
            if (e.dataTransfer == null) return;
            var files = [];
            for (var i in e.dataTransfer.files) {
                if ((e.dataTransfer.files[i].type != null) && (e.dataTransfer.files[i].size != null) && (e.dataTransfer.files[i].size != 0) && (e.dataTransfer.files[i].name.endsWith('.mcrec'))) {
                    files.push(e.dataTransfer.files[i]);
                }
            }
            if (files.length == 0) return;
            srec_cleanup();
            recFile = files[0];
            recFilePtr = 0;
            readNextBlock(processFirstBlock);
            readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
            srec_restart();
        }

        function srec_openfile() {
            var x = '<input type=file name=files id=srec_p2fileinput style=width:100% accept=".mcrec" onchange="openfileChanged()" />';
            setDialogMode(11, "Fichier ouvert...", 3, srec_openfileEx, x);
            QE('idx_dlgOkButton', false);
        }

        function srec_openfileEx() {
            var xfiles = Q('srec_p2fileinput').files;
            if (xfiles != null) { var files = []; for (var i in xfiles) { if ((xfiles[i].type != null) && (xfiles[i].size != null) && (xfiles[i].size != 0) && (xfiles[i].name.endsWith('.mcrec'))) { files.push(xfiles[i]); } } }
            if (files.length == 0) return;
            srec_cleanup();
            recFile = files[0];
            recFilePtr = 0;
            readNextBlock(processFirstBlock);
            readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
            Q('srec_OpenFileButton').blur();
        }

        function openfileChanged() {
            var xfiles = Q('srec_p2fileinput').files;
            if (xfiles != null) { var files = []; for (var i in xfiles) { if ((xfiles[i].type != null) && (xfiles[i].size != null) && (xfiles[i].size != 0) && (xfiles[i].name.endsWith('.mcrec'))) { files.push(xfiles[i]); } } }
            QE('idx_dlgOkButton', files.length == 1);
        }

        function srec_togglePause() {
            if (recFile != null) { if (srec_playing == 2) { srec_pause(); } else { if (recFilePtr != recFile.size) { srec_play(); } } } return false;
        }

        function srec_play() {
            Q('srec_PlayButton').blur();
            if ((srec_playing == 2) || (recFileProtocol == 0)) return;
            srec_playing = 2;
            QV('srec_metadatadiv', false);
            QE('srec_PlayButton', false);
            QE('srec_PauseButton', true);
            QE('srec_RestartButton', false);
            if ((recFileProtocol == 2) || (recFileProtocol == 101) || (recFileProtocol == 200)) {
                QV('srec_DeskParent', true);
                QV('srec_TermParent', false);
            } else if ((recFileProtocol == 1) && (agentTerminal == null)) {
                QV('srec_DeskParent', false);
                QV('srec_TermParent', true);
                agentTerminal = CreateAmtRemoteTerminal('srec_Term', {});
                agentTerminal.State = 3;
                agentTerminal.heightLock = 1;
            }
            readNextBlock(processBlock);
        }

        function srec_pause() {
            Q('srec_PauseButton').blur();
            if (srec_playing < 2) return;
            srec_playing = 1;
            QE('srec_PlayButton', recFilePtr != recFile.size);
            QE('srec_PauseButton', false);
            QE('srec_RestartButton', recFilePtr != 0);
            if (waitTimer != null) {
                clearTimeout(waitTimer);
                waitTimer = null;
                processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]);
                waitTimerArgs = null;
            }
        }

        function srec_restart() {
            Q('srec_RestartButton').blur();
            if (srec_playing == 0) return;
            recFilePtr = 0;
            readState = 0;
            currentDeltaTimeTotalSec = 0;
            QV('srec_metadatadiv', true);
            QE('srec_PlayButton', true);
            QE('srec_PauseButton', false);
            QE('srec_RestartButton', false);
            QS('srec_progressbar').width = '0px';
            QH('srec_timespan', '00:00:00');
            QV('srec_DeskParent', false);
            QV('srec_TermParent', false);
            if (agentDesktop) {
                agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height);
            }
            if (amtDesktop) {
                amtDesktop.canvas.clearRect(0, 0, amtDesktop.canvasid.width, amtDesktop.canvasid.height);
                amtDesktop = CreateAmtRemoteDesktop('srec_Desk');
                amtDesktop.onScreenSizeChange = srec_deskAdjust;
                amtDesktop.State = 3;
                amtDesktop.Start();
                if (recFileMetadata.protocol == 200) {
                    if (recFileMetadata.bpp) { amtDesktop.bpp = recFileMetadata.bpp; }
                    if (recFileMetadata.graymode) { amtDesktop.graymode = recFileMetadata.graymode; }
                    if (recFileMetadata.lowcolor) { amtDesktop.lowcolor = recFileMetadata.lowcolor; }
                    amtDesktop.state = 3;
                    srec_deskAdjust();
                }
            }
            if (agentTerminal) { agentTerminal = null; }
        }

        function clearConsoleMsg() {
            //QH('srec_p11DeskConsoleMsg', '');
        }

        // Toggle the web page to full screen
        function srec_toggleAspectRatio(toggle) {
            if (toggle === 1) { srec_deskAspectRatio = ((srec_deskAspectRatio + 1) % 3); }
            srec_deskAdjust();
        }

        function srec_deskAdjust() {
            var parentH = Q('srec_DeskParent').clientHeight, parentW = Q('srec_DeskParent').clientWidth;
            var deskH = Q('srec_Desk').height, deskW = Q('srec_Desk').width;
            QS('srec_Desk')['margin-top'] = null;
            QS('srec_Desk')['margin-left'] = null;

            if (srec_deskAspectRatio == 2) {
                // Scale mode
                QS('srec_Desk')['margin-top'] = null;
                QS('srec_Desk').height = '100%';
                QS('srec_Desk').width = '100%';
                QS('srec_DeskParent').overflow = 'hidden';
            } else if (srec_deskAspectRatio == 1) {
                // Zoomed mode
                QS('srec_Desk')['margin-top'] = '0px';
                QS('srec_Desk').height = deskH + 'px';
                QS('srec_Desk').width = deskW + 'px';
                QS('srec_DeskParent').overflow = 'scroll';
            } else {
                // Fixed aspect ratio
                if ((parentH / parentW) > (deskH / deskW)) {
                    var hNew = ((deskH * parentW) / deskW) + 'px';
                    QS('srec_Desk').height = hNew;
                    QS('srec_Desk').width = '100%';
                    QS('srec_Desk')['margin-top'] = ((parentH - ((deskH * parentW) / deskW)) / 2) + 'px';
                } else {
                    var wNew = ((deskW * parentH) / deskH) + 'px';
                    QS('srec_Desk').height = '100%';
                    QS('srec_Desk').width = wNew;
                    QS('srec_Desk')['margin-left'] = ((parentW - ((deskW * parentH) / deskH)) / 2) + 'px'
                }
                QS('srec_DeskParent').overflow = 'hidden';
            }
        }

        function pad2(num) { var s = '00' + num; return s.substr(s.length - 2); }

        // ###END###{SessionRecording}

        //
        // POPUP DIALOG
        //

        // undefined = Hidden, 1 = Generic Message
        var xxdialogMode;
        var xxdialogFunc;
        var xxdialogButtons;
        var xxdialogTag;

        // Display a dialog box
        // Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 11 only)
        function setDialogMode(x, y, b, f, c, tag) {
            xxdialogMode = x;
            xxdialogFunc = f;
            xxdialogButtons = b;
            xxdialogTag = tag;
            QE('idx_dlgOkButton', true);
            QV('idx_dlgOkButton', b & 1);
            QV('idx_dlgCancelButton', b & 2);
            QV('id_dialogclose', b & 2);
            QV('idx_dlgDeleteButton', b & 4);
            if (y) QH('id_dialogtitle', y);
            for (var i = 1; i < 28; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
            QV('dialog', x);
            if (c) { if (x == 11) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }

            // ###BEGIN###{IDERStats}
            if (xxdialogMode != 0) { iderToggleDiskMap(false); }
            // ###END###{IDERStats}
        }

        function dialogclose(x) {
            var f = xxdialogFunc, b = xxdialogButtons, t = xxdialogTag;
            setDialogMode();
            if (((b & 8) || x) && f) f(x, t);
        }

        function center() {
            QS('dialog').left = ((((getDocWidth() - 400) / 2)) + 'px');
            // ###BEGIN###{Desktop}
            var sh = 0, mh = (Q('id_mainarea').offsetHeight - ((fullscreen == false)?126:53));
            // ###BEGIN###{Scripting}
            if (QS('id_scriptstatus').display == '') sh += 32; // If script status is displayed, reduce max-height by 22 pixels
            // ###END###{Scripting}
            // ###BEGIN###{IDER}
            if (QS('id_iderstatus').display == '') sh += 32; // If ider status is displayed, reduce max-height by 22 pixels
            // ###END###{IDER}
            QS('id_mainarea_pad').height = (Q('id_mainarea').offsetHeight - sh - ((fullscreen == false)?16:0)) + 'px';
            QS('Desk')['max-height'] =  (mh - sh) + 'px';
            QS('Desk')['max-width'] = (Q('id_mainarea').offsetWidth - ((fullscreen == false)?32:0)) + 'px';
            if (Q('id_DeskParent').offsetWidth != 0) { QS('Desk')['max-width'] = Q('id_DeskParent').offsetWidth; }
            if (fullscreen) {
                QS('id_mainarea_pad')['overflow-y'] = 'hidden';
                var h = (mh - sh - Q('Desk').offsetHeight) / 2;
                QS('Desk')['margin-top'] = h + 'px';
                QS('Desk')['margin-bottom'] = h + 'px';
            } else {
                QS('id_mainarea_pad')['overflow-y'] = 'scroll';
                QS('Desk')['margin-top'] = '0';
                QS('Desk')['margin-bottom'] = '0';
            }
            // ###END###{Desktop}
            // ###BEGIN###{Storage}
            //QS('id_mainarea_frame').height = Q('id_mainarea').offsetHeight;
            // ###END###{Storage}

            // ###BEGIN###{SessionRecording}
            srec_deskAdjust();
            // ###END###{SessionRecording}
        }
        function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
        function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }

        //
        // GENERIC METHODS
        //

        // ###BEGIN###{FileSaver}
        function SaveJsonFile(name, name2, desc, data) {
            var n = '', r = {}, d = new Date();
            if (amtsysstate) {
                n = '-' + amtsysstate['AMT_GeneralSettings'].response['HostName'];
                r = {'webappversion':version,'description':desc,'hostname':amtsysstate['AMT_GeneralSettings'].response['HostName'],'localtime':Date(),'utctime':new Date().toUTCString(),'isotime':new Date().toISOString()};
                if (HardwareInventory) r['systemid'] = guidToStr(HardwareInventory['CIM_ComputerSystemPackage'].response['PlatformGUID'].toLowerCase());
            }
            n += '-' + d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);;
            r[name2] = data;
            // ###BEGIN###{!Mode-NodeWebkit}
            saveAs(data2blob(JSON.stringify(r, null, '  ').replace(/\n/g, '\r\n')), name + n + '.json');
            // ###END###{!Mode-NodeWebkit}
            // ###BEGIN###{Mode-NodeWebkit}
            var chooser = document.createElement('input');
            chooser.setAttribute('type', 'file')
            chooser.setAttribute('nwsaveas', name + n + '.json');
            chooser.addEventListener('change', function () { require('fs').writeFile(this.value, JSON.stringify(r, null, '  ').replace(/\n/g, '\r\n'), function () { }); }, false);
            chooser.click();
            // ###END###{Mode-NodeWebkit}
        }
        // ###END###{FileSaver}

        var httpErrorTable = {
            200: "D'accord",
            401: "Erreur d'authentification",
            408: "Erreur de temporisation",
            601: "Erreur d'analyse WSMAN",
            602: "Impossible d'analyser l'en-tête de réponse HTTP",
            603: "Réponse d'énumération HTTP inattendue",
            604: "Réponse de pull HTTP inattendue",
            // ###BEGIN###{Mode-NodeWebkit}
            998: "Certificat TLS non valide",
            // ###END###{Mode-NodeWebkit}
            997: "Domaine de résumé non valide"
        }
        function errcheck(s, stack) {
            if (wsstack == null || amtstack != stack) return true;
            if (s != 200 && s != 9) {
                setDialogMode();
                wsstack.comm.FailAllError = 999; // Cause all new responses to be silent
                amtstack.CancelAllQueries(999);
                QH('id_messageviewstr', ((httpErrorTable[s])?(httpErrorTable[s]):(format("Erreur # {0}", s))));
                // ###BEGIN###{Mode-MeshCentral2}
                if (s == 401) { QH('id_messageviewstr', "Erreur d'authentification" + '<br /><br /><input type=button value=\"' + "Set new credentials" + '\" onclick=meshcentral2credCallback(true)></input>'); }
                // ###END###{Mode-MeshCentral2}
                go(100);
                QS('id_progressbar').width = 0;
                // ###BEGIN###{ComputerSelector}
                Q('id_messageviewbutton').focus();
                // ###END###{ComputerSelector}

                // ###BEGIN###{Mode-NodeWebkit}
                if (s == 998) {
                    //console.log('errcheck', wsstack.comm.xtlsCertificate.fingerprint);
                    if (wsstack.comm.xtlsCertificate != null) {
                        showTlsCert(11, '<img style=float:left;margin-right:8px src=warning.png width=48 height=48><div style=min-height:48px;display:table><div style=display:table-cell;vertical-align:middle>' + "Intel&reg; AMT connecté avec le certificat suivant. Appuyez sur Annuler pour vous déconnecter s'il ne s'agit pas du certificat attendu." + '</div></div>', wsstack.comm.xtlsCertificate, 1);
                    }
                }
                // ###END###{Mode-NodeWebkit}
            }
            return (s != 200);
        }

        // ###BEGIN###{Storage}
        function goiFrame(e,x,y) {
            if (xxdialogMode) return;
            go(x);
            // ###BEGIN###{Mode-NodeWebkit}
            var ports = portsFromHost(currentcomputer['host'], currentcomputer['tls']);
            y = (currentcomputer['tls']==0?'http://':'https://') + ports.host + ':' + ports.http + y;
            // ###END###{Mode-NodeWebkit}
            if ((e.shiftKey == true) || (Q('id_StorageIFrame').src.endsWith(y) == false)) Q('id_StorageIFrame').src = y;
            QV('id_mainarea_pad', false);
            QV('id_mainarea_frame', true);
        }
        // ###END###{Storage}

        function go(x, force) {
            if (xxdialogMode && force != 1) return;
            // ###BEGIN###{Mode-NodeWebkit}
            // Remove left bar selection
            var leftBarItems = ['LeftMenuMyDevices', 'LeftMenuMyCerts', 'LeftMenuMyUsb'];
            // ###BEGIN###{SessionRecording}
            leftBarItems.push('LeftMenuPlayer');
            // ###END###{SessionRecording}
            for (var i in leftBarItems) { Q(leftBarItems[i]).classList.remove('lbbuttonsel'); Q(leftBarItems[i]).classList.remove('lbbuttonsel2'); }
            if (x == 101) { Q('LeftMenuMyDevices').classList.add('lbbuttonsel2'); }
            if (x == 103) { Q('LeftMenuMyCerts').classList.add('lbbuttonsel2'); }
            if (x == 102) { Q('LeftMenuMyUsb').classList.add('lbbuttonsel2'); }
            if (x == 104) { Q('LeftMenuPlayer').classList.add('lbbuttonsel2'); }
            QV('LeftSideToolBar', ((x >= 101) && (x <= 104)));
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{Storage}
            QV('id_mainarea_frame', false);
            QV('id_mainarea_pad', true);
            // ###END###{Storage}
            // ###BEGIN###{ComputerSelector}
            QV('id_computerSelector', x == 101);
            // ###END###{ComputerSelector}
            // ###BEGIN###{Mode-LMS}
            QV('id_lmsMainPanel', x == 101);
            // ###END###{Mode-LMS}
            // ###BEGIN###{USBSetup}
            QV('id_usbSetupPanel', x == 102);
            // ###END###{USBSetup}
            // ###BEGIN###{CertificateManager}
            QV('id_certManagerPanel', x == 103);
            // ###END###{CertificateManager}
            // ###BEGIN###{SessionRecording}
            QV('id_sessionPlayerPanel', x == 104);
            // ###END###{SessionRecording}
            QV('id_messageview', x == 100);
            QV('id_mainview', x < 100);
            for (var i = 0; i < 80; i++) { // Edit this line when adding a new screen
                QV('p' + i, i == x);
                var q = QS('go' + i);
                // ###BEGIN###{Look-Intel}
                if (q) { q['background-color'] = ((i == x)?'#abcae1':''); } // #e8eefe
                // ###END###{Look-Intel}
                // ###BEGIN###{Look-ISDU}
                if (q) { q['background-color'] = ((i == x)?'#abcae1':''); } // #e8eefe
                // ###END###{Look-ISDU}
                // ###BEGIN###{Look-BrandedCommander}
                if (q) { q['background-color'] = ((i == x)?'#abcae1':''); } // #e8eefe
                // ###END###{Look-BrandedCommander}
                // ###BEGIN###{Look-Unite}
                if (q) { q['background-color'] = ((i == x)?'#abcae1':''); } // #e8eefe
                // ###END###{Look-Unite}
                // ###BEGIN###{Look-Commander}
                if (q) { q['background-color'] = ((i == x)?'gray':''); }
                // ###END###{Look-Commander}
                // ###BEGIN###{Look-MeshCentral}
                if (q) { q['background-color'] = ((i == x)?'gray':''); }
                // ###END###{Look-MeshCentral}
            }
            currentView = x;
            // ###BEGIN###{Look-ISDU}
            QV('id_isdu-image1', x == 11);
            QV('id_isdu-image2', x == 8);
            QV('id_isdu-image3', x == 14 || x == 13);
            QV('id_isdu-image4', x == 1 || x == 0);
            QV('id_isdu-image5', x == 6 || x == 15);
            QV('id_isdu-image6', x == 18 || x == 19);
            QV('id_isdu-image7', x == 16 || x == 12 || x == 2);
            QV('id_isdu-image8', x == 17);
            // ###END###{Look-ISDU}
            // ###BEGIN###{Look-BrandedCommander}
            // ###BEGIN###{!Mode-Firmware}
            QV('id_isdu-image1', x == 11);
            QV('id_isdu-image2', x == 8);
            QV('id_isdu-image3', x == 14 || x == 13);
            QV('id_isdu-image4', x == 1 || x == 0);
            QV('id_isdu-image5', x == 6 || x == 15);
            QV('id_isdu-image6', x == 18 || x == 19);
            QV('id_isdu-image7', x == 16 || x == 12 || x == 2);
            QV('id_isdu-image8', x == 17);
            // ###END###{!Mode-Firmware}
            // ###END###{Look-BrandedCommander}
            // ###BEGIN###{Mode-NodeWebkit}
            NW_SetupMainMenu(x);
            // ###END###{Mode-NodeWebkit}
            // ###BEGIN###{Desktop}
            center();
            // ###END###{Desktop}
        }

        function portsFromHost(host, tls) {
            host = decodeURIComponent(host);
            var x = host.split(':'), hp = ((tls == 0) ? 16992 : 16993), rp = ((tls == 0) ? 16994 : 16995);
            if (x[0].indexOf('[') == 0) { // IPv6 address
                x = host.split(']:');
                if (x.length == 1) { return { host: host.substring(1, host.length - 1), http: hp, redir: rp } }
                if (x.length > 1) { var y = x[1].split(':'); if (y.length > 0) { hp = parseInt(y[0]); } if (y.length > 1) { rp = parseInt(y[1]); } }
                return { host: x[0].substring(1), http: hp, redir: rp }
            }
            if (x.length > 1) { hp = parseInt(x[1]); }
            if (x.length > 2) { rp = parseInt(x[2]); }
            return { host: x[0], http: hp, redir: rp }
        }
        function addLink(x, f) { return '<a style=cursor:pointer;color:blue onclick=\'' + f + '\'>&diams; ' + x + '</a>'; }
        function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
        function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
        function addOption(q, t, i) { var option = document.createElement('option'); option.text = t; option.value = i; Q(q).add(option); }
        function addDisabledOption(q, t, i) { var option = document.createElement('option'); option.text = t; option.value = i; option.disabled = 1; Q(q).add(option); }
        function passwordcheck(p) { if (p.length < 8) return false; var upper = 0, lower = 0, number = 0, nonalpha = 0; for (var i in p) { var c = p.charCodeAt(i); if ((c > 64) && (c < 91)) { upper = 1; } else if ((c > 96) && (c < 123)) { lower = 1; } else if ((c > 47) && (c < 58)) { number = 1; } else { nonalpha = 1; } } return ((upper + lower + number + nonalpha) == 4); }
        function methodcheck(r) { if (r && r != null && r.Body && r.Body['ReturnValue'] != 0) { messagebox("Erreur d'appel", r.Header['Method'] + ': ' + (r.Body.ReturnValueStr + '').replace('_', ' ')); return true; } return false; }
        function TableStart() { return '<table class=\'log1 us\' cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td width=200px><p><td>'; }
        function TableStart2() { return '<table class=\'log1 us\' cellpadding=0 cellspacing=0 style=width:100%;border-radius:8px><tr><td><p><td>'; }
        function TableEntry(n, v) { return '<tr><td class=r1><p>' + n + '<td class=r1>' + v; }
        function FullTable(x, e) { var r = TableStart(); for (i in x) { if (i && x[i]) r += TableEntry(i, x[i]); } return r + TableEnd(e); }
        function TableEnd(n) { return '<tr><td colspan=2><p>' + (n?n:'') + '</table>'; }
        function AddButton(v, f) { return '<input type=button value=\'' + v + '\' onclick=\'' + f + '\' style=margin:4px>'; }
        function AddButton2(v, f, s) { return '<input type=button value=\'' + v + '\' onclick=\'' + f + '\' ' + s + '>'; }
        function AddRefreshButton(f) { return '<input type=button name=refreshbtn value="' + "Rafraîchir" + '" onclick=\'refreshButtons(false);' + f + '\' style=margin:4px ' + (refreshButtonsState==false?'disabled':'') + '>'; }
        function MoreStart() { return '<a style=cursor:pointer;color:blue id=morexxx1 onclick=QV(\"morexxx1\",false);QV(\"morexxx2\",true)>&#x25BC; ' + "More" + '</a><div id=morexxx2 style=display:none><br><hr>'; };
        function MoreEnd() { return '<a style=cursor:pointer;color:blue onclick=QV(\"morexxx2\",false);QV(\"morexxx1\",true)>&#x25B2; ' + "Less" + '</a></div>'; };
        function getSelectedOptions(sel) { var opts = [], opt; for (var i = 0, len = sel.options.length; i < len; i++) { opt = sel.options[i]; if (opt.selected) { opts.push(opt.value); } } return opts; }
        function getInstance(x, y) { for (var i in x) { if (x[i]['InstanceID'] == y) return x[i]; } return null; }
        function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; }
        function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + '-' + g.substring(10, 12) + g.substring(8, 10) + '-' + g.substring(14, 16) + g.substring(12, 14) + '-' + g.substring(16, 20) + '-' + g.substring(20); }
        function getUrlVars() { var j, hash, vars = [], hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for (var i = 0; i < hashes.length; i++) { j = hashes[i].indexOf('='); if (j > 0) { vars[hashes[i].substring(0, j)] = hashes[i].substring(j + 1, hashes[i].length); } } return vars; }
        function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
        function getDocHeight() { if (window.innerHeight) return window.innerHeight; if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientHeight != 0) return document.documentElement.clientHeight; return document.getElementsByTagName('body')[0].clientHeight; }
        function addHtmlValue(t, v) { return '<div style=height:20px><div style=float:right;width:220px;overflow:hidden><b title="' + v + '">' + v + '</b></div><div>' + t + '</div></div>'; }
        function addHtmlValueNoTitle(t, v) { return '<div style=height:20px><div style=float:right;width:220px;overflow:hidden>' + v + '</b></div><div>' + t + '</div></div>'; }
        function numbersOnly(e, x) { return (event.charCode == 0) || (event.charCode == x) || (event.charCode >= 48 && event.charCode <= 57); }
        function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };

// ###BEGIN###{**ClosureAdvancedMode}
        // Google closure advanced mode externs
        window['cleanup'] = cleanup;
        window['disconnect'] = disconnect;
        window['dialogclose'] = dialogclose;
        window['go'] = go;
        window['QV'] = QV;
        window['numbersOnly'] = numbersOnly;
        window['syncClock'] = syncClock;
        window['showLinkPolicyDlg'] = showLinkPolicyDlg;
        // ###BEGIN###{PowerControl}
        window['showPowerActionDlg'] = showPowerActionDlg;
        // ###BEGIN###{PowerControl-Advanced}
        window['showAdvPowerDlg'] = showAdvPowerDlg;
        window['showAdvPowerDlgChange'] = showAdvPowerDlgChange;
        // ###END###{PowerControl-Advanced}
        // ###END###{PowerControl}
        window['showFeaturesDlg'] = showFeaturesDlg;
        window['showConsentDlg'] = showConsentDlg;
        // ###BEGIN###{NetworkSettings}
        window['showPingActionDlg'] = showPingActionDlg;
        window['showIPSetupDlg'] = showIPSetupDlg;
        window['updateIPSetupDlg'] = updateIPSetupDlg;
        window['showIPv6StateDlg'] = showIPv6StateDlg;
        window['showIPv6AddrDlg'] = showIPv6AddrDlg;
        // ###END###{NetworkSettings}
        window['PullSystemStatus'] = PullSystemStatus;
        window['changeAccountButton'] = changeAccountButton;
        window['changeAccountStateButton'] = changeAccountStateButton;
        window['newAccountButton'] = newAccountButton;
        window['showUserDetails'] = showUserDetails;
        window['showEditDnsDlg'] = showEditDnsDlg;
        window['showEditDnsDlgChange'] = showEditDnsDlgChange;
        window['setDialogMode'] = setDialogMode;
        window['PullUserInfo'] = PullUserInfo;
        window['toggleAccountButton'] = toggleAccountButton;
        window['showEditNameDlg'] = showEditNameDlg;
        window['updateAccountDialog'] = updateAccountDialog;
        window['refreshButtons'] = refreshButtons;
        window['showPowerPolicyDlg'] = showPowerPolicyDlg;
        // ###BEGIN###{HardwareInfo}
        window['PullHardware'] = PullHardware;
        // ###BEGIN###{FileSaver}
        window['SaveHardwareLog'] = SaveHardwareLog;
        // ###END###{FileSaver}
        // ###END###{HardwareInfo}
        // ###BEGIN###{WsmanBrowser}
        // ###BEGIN###{FileSaver}
        window['saveEntireAmtState'] = saveEntireAmtState;
        // ###END###{FileSaver}
        // ###END###{WsmanBrowser}
        // ###BEGIN###{ContextMenus}
        window['handleContextMenu'] = handleContextMenu;
        window['hideContextMenu'] = hideContextMenu;
        // ###END###{ContextMenus}
        // ###BEGIN###{Mode-NodeWebkit}
        window['showTlsCert'] = showTlsCert;
        window['downloadTlsCert'] = downloadTlsCert;
        // ###END###{Mode-NodeWebkit}

        // ###BEGIN###{Desktop}
        window['connectDesktopButton'] = connectDesktopButton;
        window['connectDesktop'] = connectDesktop;
        window['deskToggleFull'] = deskToggleFull;
        window['showDesktopSettings'] = showDesktopSettings;
        window['dmousedown'] = dmousedown;
        window['dmouseup'] = dmouseup;
        window['dmousemove'] = dmousemove;
        window['drotate'] = drotate;
        window['sendCAD'] = sendCAD;
        // ###BEGIN###{FileSaver}
        window['deskSaveImage'] = deskSaveImage;
        // ###END###{FileSaver}
        // ###BEGIN###{DesktopFocus}
        window['deskToggleFocus'] = deskToggleFocus;
        // ###END###{DesktopFocus}
        // ###BEGIN###{Desktop-Multi}
        window['desktopSwitchScreen'] = desktopSwitchScreen;
        // ###END###{Desktop-Multi}
        // ###END###{Desktop}

        // ###BEGIN###{Desktop-Settings}
        window['showDesktopSettingsDlg'] = showDesktopSettingsDlg;
        window['showDesktopSettingsDlgUpdate'] = showDesktopSettingsDlgUpdate;
        // ###END###{Desktop-Settings}

        // ###BEGIN###{Terminal}
        window['connectTerminal'] = connectTerminal;
        window['termPaste'] = termPaste;
        window['termSendKey'] = termSendKey;
        // ###BEGIN###{FileSaver}
        window['terminalCaptureToggle'] = terminalCaptureToggle;
        // ###END###{FileSaver}
        // ###BEGIN###{TerminalSize}
        window['termToggleSize'] = termToggleSize;
        // ###END###{TerminalSize}
        window['termToggleFx'] = termToggleFx;
        // ###BEGIN###{Terminal-Enumation-All}
        window['termToggleType'] = termToggleType;
        // ###END###{Terminal-Enumation-All}
        window['termPaste'] = termPaste;
        // ###END###{Terminal}

        // ###BEGIN###{IDER}
        window['iderStart'] = iderStart;
        window['iderStop'] = iderStop;
        // ###BEGIN###{IDERStats}
        window['iderToggleDiskMap'] = iderToggleDiskMap;
        // ###END###{IDERStats}
        // ###END###{IDER}

        // ###BEGIN###{RemoteAccess}
        window['editEnvironmentDetection'] = editEnvironmentDetection;
        window['editEnvironmentDetectionAdd'] = editEnvironmentDetectionAdd;
        window['editUserInitiatedCira'] = editUserInitiatedCira;
        window['editMpsPolicy'] = editMpsPolicy;
        window['showServerDetails'] = showServerDetails;
        window['AddRemoteAccessServer'] = AddRemoteAccessServer;
        window['AddRemoteAccessServerUpdate'] = AddRemoteAccessServerUpdate;
        window['edInputChg'] = edInputChg;
        window['editMpsPolicyUpdate'] = editMpsPolicyUpdate;
        window['editEnvironmentDetectionRemove'] = editEnvironmentDetectionRemove;
        // ###END###{RemoteAccess}

        // ###BEGIN###{EventLog}
        window['showEventDetails'] = showEventDetails;
        window['PullEventLog'] = PullEventLog;
        window['FreezeLog'] = FreezeLog;
        window['ClearLog'] = ClearLog;
        window['eventFilter'] = eventFilter;
        // ###BEGIN###{FileSaver}
        window['SaveEventLog'] = SaveEventLog;
        // ###END###{FileSaver}
        // ###END###{EventLog}

        // ###BEGIN###{AuditLog}
        window['PullAuditLog'] = PullAuditLog;
        window['auditFilter'] = auditFilter;
        window['showAuditDetails'] = showAuditDetails;
        // ###BEGIN###{FileSaver}
        window['SaveAuditLog'] = SaveAuditLog;
        // ###END###{FileSaver}
        // ###END###{AuditLog}

        // ###BEGIN###{Certificates}
        window['PullCertificates'] = PullCertificates;
        window['showCertDetails'] = showCertDetails;
        window['addCertButton'] = addCertButton;
        window['issueCertButton'] = issueCertButton;
        window['showSetTlsSecurityDlg'] = showSetTlsSecurityDlg;
        window['showSetTlsSecurityDlgUpdate'] = showSetTlsSecurityDlgUpdate;
        window['showKeyPairDetails'] = showKeyPairDetails;
        window['addCertButtonUpdate'] = addCertButtonUpdate;
        window['issueCertButtonUpdate'] = issueCertButtonUpdate;
        // ###BEGIN###{FileSaver}
        window['downloadCert'] = downloadCert;
        // ###END###{FileSaver}
        // ###END###{Certificates}

        // ###BEGIN###{AgentPresence}
        window['addWatchdogAction'] = addWatchdogAction;
        window['deleteWatchdogActions'] = deleteWatchdogActions;
        window['PullWatchdog'] = PullWatchdog;
        window['AddWatchdog'] = AddWatchdog;
        window['AddWatchdogUpdate'] = AddWatchdogUpdate;
        window['addWatchdogActionUpdate'] = addWatchdogActionUpdate;
        window['showWatchdogDetails'] = showWatchdogDetails;
        window['GenerateWatchdogGuid'] = GenerateWatchdogGuid;
        // ###END###{AgentPresence}

        // ###BEGIN###{SystemDefense}
        window['changeDefaultPolicy'] = changeDefaultPolicy;
        window['AddDefenseFilter'] = AddDefenseFilter;
        window['AddDefenseFilterUpdate'] = AddDefenseFilterUpdate;
        window['showFilterDetails'] = showFilterDetails;
        window['AddDefensePolicy'] = AddDefensePolicy;
        window['addFilterButton'] = addFilterButton;
        window['removeFilterButton'] = removeFilterButton;
        window['AddDefensePolicyUpdate'] = AddDefensePolicyUpdate;
        window['showPolicyDetails'] = showPolicyDetails;
        window['deleteDefensePolicy'] = deleteDefensePolicy;
        // ###END###{SystemDefense}

        // ###BEGIN###{Wireless}
        window['showWifiStateDlg'] = showWifiStateDlg;
        window['showWifiDetails'] = showWifiDetails;
        window['wifiRemoveButton'] = wifiRemoveButton;
        window['showWifiNewProfile'] = showWifiNewProfile;
        window['updateWifiDialog'] = updateWifiDialog;
        window['wifiRefresh'] = wifiRefresh;
        // ###END###{Wireless}

        // ###BEGIN###{WsmanBrowser}
        window['wsmanQuery'] = wsmanQuery;
        window['wsmanFilter'] = wsmanFilter;
        window['QH'] = QH;
        window['QV'] = QV;
        // ###END###{WsmanBrowser}
        
        // ###BEGIN###{Alarms}
        window['PullAlarms'] = PullAlarms;
        window['RemoveAllAlarms'] = RemoveAllAlarms;
        window['showAddAlarm'] = showAddAlarm;
        window['showAlertDetails'] = showAlertDetails;
        window['alertDialogUpdate'] = alertDialogUpdate;
        // ###END###{Alarms}

        // ###BEGIN###{ComputerSelector}
        window['computerConnect'] = computerConnect;
        window['toolmenuclick'] = toolmenuclick;
        window['computerFilterFunc'] = computerFilterFunc;
        window['computerSelect'] = computerSelect;
        
        // ###BEGIN###{ComputerSelector-Local}
        window['updateComputerDialog'] = updateComputerDialog;
        window['computerEdit'] = computerEdit;
        window['addComputer'] = addComputer;
        window['newComputerList'] = newComputerList;
        window['openComputerList'] = openComputerList;
        window['saveComputerList'] = saveComputerList;
        // ###END###{ComputerSelector-Local}

        // ###BEGIN###{Scripting}
        window['computerStopScript'] = computerStopScript;
        window['mscript_runScriptDlg'] = mscript_runScriptDlg;
        window['onComputerChecked'] = onComputerChecked;
        window['mscript_showComputerScriptOutput'] = mscript_showComputerScriptOutput;
        // ###END###{Scripting}

        // ###BEGIN###{ComputerSelectorScanner}
        // ###BEGIN###{Mode-NodeWebkit}
        window['showScanDialog'] = showScanDialog;
        window['showScanDialogUpdate'] = showScanDialogUpdate;
        // ###END###{Mode-NodeWebkit}
        // ###END###{ComputerSelectorScanner}

        // ###END###{ComputerSelector}

        // ###BEGIN###{Mode-LMS}
        window['lmsRefresh'] = lmsRefresh;
        window['lmsConfigure'] = lmsConfigure;
        window['lmsLogin'] = lmsLogin;
        window['lmsConfigureLogin'] = lmsConfigureLogin;
        window['lmsUpdateLoginDialog'] = lmsUpdateLoginDialog;
        window['lmsShowVersionsDlg'] = lmsShowVersionsDlg;
        window['lmsActivate'] = lmsActivate;
        window['lmsDeactivate'] = lmsDeactivate;
        window['toolmenuclick'] = toolmenuclick;
        window['lmsShowTrustedHashesDlg'] = lmsShowTrustedHashesDlg;
        // ###END###{Mode-LMS}

        // ###BEGIN###{Storage}
        window['SetStorageName'] = SetStorageName;
        window['showStorageDetails'] = showStorageDetails;
        window['PullStorage'] = PullStorage;
        window['UploadToStorage'] = UploadToStorage;
        window['goiFrame'] = goiFrame;
        // ###BEGIN###{Mode-Firmware}
        window['OpenFromStorage'] = OpenFromStorage;
        // ###END###{Mode-Firmware}
        // ###BEGIN###{Mode-LMS}
        window['OpenFromStorage'] = OpenFromStorage;
        // ###END###{Mode-LMS}
        // ###BEGIN###{FileSaver}
        window['DownloadFromStorage'] = DownloadFromStorage;
        // ###END###{FileSaver}
        // ###BEGIN###{Mode-NodeWebkit}
        window['UploadAppToStorage'] = UploadAppToStorage;
        // ###END###{Mode-NodeWebkit}
        // ###END###{Storage}

        // ###BEGIN###{Scripting}
        window['script_runScriptDlg'] = script_runScriptDlg;
        window['script_Stop'] = script_Stop;
        // ###END###{Scripting}

        // ###BEGIN###{Scripting-Editor}
        // ###BEGIN###{FileSaver}
        window['script_saveScript'] = script_saveScript;
        // ###END###{FileSaver}
        window['resetScriptButton'] = resetScriptButton;
        window['runScriptButton'] = runScriptButton;
        window['breakScriptButton'] = breakScriptButton;
        window['stepScriptButton'] = stepScriptButton;
        window['scriptViewButton'] = scriptViewButton;
        window['script_fonfilterchanged'] = script_fonfilterchanged;
        window['script_fonclick'] = script_fonclick;
        window['script_fondragstart'] = script_fondragstart;
        window['script_fondragend'] = script_fondragend;
        window['script_fondragenter'] = script_fondragenter;
        window['script_fondragleave'] = script_fondragleave;
        window['script_fondrop'] = script_fondrop;
        window['script_foneditclick'] = script_foneditclick;
        window['script_foneditclickEx'] = script_foneditclickEx;
        // ###END###{Scripting-Editor}

        // ###BEGIN###{USBSetup}
        window['usb_newSetupBin'] = usb_newSetupBin;
        window['usb_openSetupBin'] = usb_openSetupBin;
        window['usb_addRecordSetupBin'] = usb_addRecordSetupBin;
        window['usb_addvariable'] = usb_addvariable;
        window['usb_editheader'] = usb_editheader;
        window['usb_editrecord'] = usb_editrecord;
        window['usb_editvariable'] = usb_editvariable;
        window['usb_ond16typechange'] = usb_ond16typechange;
        // ###BEGIN###{FileSaver}
        window['usb_saveSetupBin'] = usb_saveSetupBin;
        // ###END###{FileSaver}
        // ###END###{USBSetup}

        // ###BEGIN###{Mode-MeshCentral2}
        window['connectButtonfunction'] = connectButtonfunction;
        // ###END###{Mode-MeshCentral2}

// ###END###{**ClosureAdvancedMode}

        // Get things started
        startup();
    </script>


</div></div></body></html>